How to make Among Us in Unity | Part 1 — Basic Gameplay and Art
Among Us — the game that took the Internet by storm. Let’s find out the secrets of this game and see how you can make a game similar to Among Us in Unity Game Engine.
Get the Game Kit and start building an Among Us-like game in minutes!
This tutorial is a companion to the How to Make Among Us in Unity series on my channel, Redefine Gamedev. If you prefer the video version, I highly recommend you check that one as well.
Episode list:
#1 — Basic Gameplay and Art (this one) [video]
#2 — Make it Multiplayer [video]
#3 — The Keypad Task [video]
#4 — The Card Swipe [video]
#5 — Player Kill functionality | Using Photon RPCs [video]
#6 — The Wire Task [video]
#7 — Multiplayer Lobby and Rooms [video]
#8 — Putting everything together [video]
#9 — Selecting the IMPOSTOR [video]
#10 — Multiplayer Chat [video]
#11 — Lights, Sounds and Animations [video]
#12 — Unlock Manifolds Task [video]
#13 — Start Reactor Task [video]
By the end of this tutorial you will have a working prototype of a game similar to Among Us.
Tools to Get You Started
Let’s get right into action with these free tools:
- Game Engine: Unity 2020 is used for this purpose
- Drawing Tool: Inkscape / Alternatively, you can use Gimp or Paint as well
- Multiplayer: Photon Cloud (has a free tier for 20 users)
How to create Basic Art
You don’t need to be an artist to create art. What you need is the will to do so. I have a video about “programmer art” where you can see different ways to make nice art for your game.
I used Draw Bezier in Inkscape but any line tool would do the job.
How to create Basic Gameplay
For the gameplay, we will focus on the following:
- Player Movement
- Camera Follow
- Environment Creation
Player Movement
2D movement is very easy to achieve in Unity. There are two main ways to go:
- Directly move the object up/down/left/right
- Move the rigidbody of the object in the desired direction
What is the main difference? The rigidbody is responsible of handling things like collision, which would be good to have for the walls. This is why we will go for the rigidbody.
In Unity an object that is simulated by physics needs two main components:
- the Rigidbody — which allows the physics engine to understand how the object should work e.g. it’s mass
- and the Collision Shape — which allows the physics engine to understand how the object looks
We will need both for our player:
After we set up everything about the object’s physics, we can proceed into transforming the object into a prefab.
A prefab acts like a blueprint e.g. you can spawn as many objects of a prefab as you want in the scene. The main benefit being that if you apply a change to one, all will change as well.
To create a prefab, drag & drop an object from the hierarchy to the project view.
For the actual movement, we will need to head over into scripting. Let’s create a new script called Move.cs:
public class Move: MonoBehaviour {
public float speed = 15; private Vector2 velocity;
private Rigidbody2D rb; private void Awake() {
rb = GetComponent<Rigidbody2D>();
velocity = Vector2.zero;
} private void Update() {
velocity.x = Input.GetAxisRaw("Horizontal");
velocity.y = Input.GetAxisRaw("Vertical");
} private void FixedUpdate() {
rb.MovePosition(rb.position +
(velocity.normalized * speed *
Time.fixedDeltaTime));
}
}
speed — the speed which the Player will move
velocity — a structure that contains 2 values X and Y and will store the direction of the movement
rb — the Rigidbody component used to manipulate the object’s physics
As for the actions in the script, we have 3 functions that are called.
private void Awake() - Called only once, when the object is created
In awake() usually we will have all the initializations. In this case, it’s the rigidbody and the velocity.
private void Update() - Called every frame
Update() is called every frame. We can use this step to gather player inputs.
private void FixedUpdate() - Physics frame update
FixedUpdate() is used to update physics objects. Here we will take the velocity which was previously initialized in Update() and apply it to the rigidbody.
rb.MovePosition(rb.position +
(velocity.normalized * speed * Time.fixedDeltaTime));
rb.position represents the current position. This is added to a product by velocity, speed and delta time. The delta time is used to make the movement frame independent.
Note: don’t forget to add the script to the player. This is done by drag & drop the script component from the project to the player in the scene (or the inspector).
Camera Follow
The camera is the object which makes the scene rendering possible. Beside the script, we need to make some changes to the camera object to adapt it to a 2d game.
Camera Adjustments — by default, Unity’s camera is set up for perspective view. Since we are developing a 2d game, it might be a good idea to change the camera rendering to orthographic.
CameraFollow.cs
public class CameraFollow : MonoBehaviour { public Transform target; public float smoothTime = 0.3f; private Vector3 velocity = Vector3.zero;
private void FixedUpdate() {
if (target == null) { return; } Vector3 targetPosition =
target.position + new Vector3(0, 0, -1); transform.position = Vector3.SmoothDamp(
transform.position,
targetPosition,
ref velocity,
smoothTime);
}
}
target — represents the current target of the Camera. To assign this, head to the inspector by selecting the camera in the scene and by using drag & drop assign the player
smoothTime — represents the smooth factor of the camera movement
velocity — is used by the Vector3.SmoothDamp function
Moving on to Update() method which runs every frame, we first need to check if the camera has a target assigned. If not, the camera cannot reposition correctly.
if (target == null) { return; }
Next, the camera’s new position needs to be computed. The value will be stored in a local variable called targetPosition.
Vector3 targetPosition =
target.position + new Vector3(0, 0, -1);
Notice that the final position is not the same as the target.position. We need this + new Vector3(0, 0, -1) to create a small displacement for the camera. This needs to be even if the camera is orthographic.
The final step is to apply the position. For this, instead of just assigning the value transform.position = transform.position, we make use of Vector3.SmoothDamp function available in Unity. This will assure a smooth transition between two different points.
transform.position = Vector3.SmoothDamp(
transform.position,
targetPosition,
ref velocity,
smoothTime);
Environment Creation
The environment is the most simple part. It’s mostly done by copy/pasting walls and floors in the scene.
Hint: make the Wall and the Floor Prefabs (they are marked with blue in the scene if they are prefabs). This way by modifying a single one will propagate to the others, simplifying the work.
Don’t forget to add a BoxCollider2D to the wall and a Rigidbody2D. Because the wall is static, we need to set the body type to Kinematic.
Want More?
You are covered! Head over to Youtube at Redefine Gamedev channel and check the video tutorial.