2D Unity Game Dev — Day 1 — Take control and move that Cube.
Learning how to simply move Unity GameObjects in two dimensions!
Objective: Learn how to move a GameObject in Unity using the keyboard ARROW or A,D,S, and W keys. Learn how to clamp the movement between two values, or “warp” the object to the opposite edge of the screen.
The basic fundamental concept of the Unity editor is that every object in your Game Scene is a GameObject. This could be a simple cube, a camera, a light source, or something more elaborate such as characters or special effects. All these Gameobjects, in turn, should be thought of as containers that hold Components. These Components are what give GameObjects functionality or behavior. They are modular in nature, and it’s up to you as the developer to adjust the properties of the components or write the behavior through a script in order to make the GameObject do what you want.
Of all the components attached to GameObjects, there is one that is common to all and which can never be removed. We are talking here about the Transform component of the GameObject.
The Transform component is used to store the position of the object in 3D space within the Unity world. Our aim in this article is to move a GameObject, changing its Transform Position in the X and Y axes using the designated keys for the horizontal and vertical axes as mapped in the Input Manager. So for the Horizontal Axis, we can use the left/right arrows, or the A and D keys. The Vertical Axis will use the up/down arrows, or the W and S keys.
Sounds good so far? Okay! Let’s create a new GameObject by selecting a 3D Object -> Cube, and rename the object Player.
Reset the Transform Position of this new object to (0, 0, 0).
Create a new script and rename it Player.
Select your Player GameObject and drag this new script into the Inspector window to add it to the Player object, or you can also drag the Player script onto the Player object in the Hierarchy.
Now open up your Player script. Add a private variable of type float called _speed and set it to 5.0f. In Unity world, this equates to the object moving 5 meters per second. Make it accessible in the Inspector by adding [SerializeField] above it. You then want to ensure the Player object is initialized in void Start() to its desired default position by calling its Position in the Transform component and setting a new Vector3 (a new position) of (0,0,0) in the X, Y, and Z axes.
Now your Game Object will reset to (0,0,0) every time you start your game. It’s in the void Start() because it only needs to be set once when everything is initialized. The next step is to command your Player object to move in the X and Y axes via keyboard inputs. Since you want these commands detected at a high frequency, you will want to write your behavior in the void Update() function. Even better yet, and to make everything much cleaner, create a new function called void CalculateMovement(), and call it from the void Update() instead. This will add clarity to your script and make it much easier to follow.
Inside your void CalculateMovement() function, declare two floats, calling one horizontalInput, the other verticalInput. Remember the designated names of the various axes in the Input Manager? This is where you use the Input.GetAxis(“Horizontal”) and assign it to the horizontalInput float. Do the same with the Input.GetAxis(“Vertical”) and the verticalInput float. It’s important that these names match exactly the ones found in the Input Manager.
It’s time to move your Player GameObject! This is done by declaring a new vector with given X, Y, and Z components (Vector3) and assigning it to the variable named direction. The X, Y, and Z components are assigned to a new instance (snapshot) of a Vector3 by reading its X (horizontalInput), Y (verticalInput) and Z (0). This is the “new Vector3” which is then stored in the variable direction.
So, let’s say for example I’m holding down the UP and LEFT arrows. This would equate the direction variable to (-1, 1, 0). If I held DOWN and RIGHT, we get (1, -1, 0).
We then use transform.Translate to move the transform by X units along the X-axis, Y units along the Y-axis, and Z units along the Z-axis as held by the direction variable. This is multiplied by the _speed variable. If _speed remains set at 5, then the maximum speed of the object in the Unity world would be +/- 5 meters per second in the X and Y axes, always zero in the Z-axis (5 m/s * 0).
Finally, we keep the rate of movement constant by multiplying everything by Time.deltaTime. This allows you to move things not by frame (which could be too fast or too slow depending on your hardware), but by time. Time. deltaTime is essentially a fragment of a second or the time passed since the last frame. So if you move something with it, it will move them by time rather than by frame.
In order to limit the movement of your Player object along the Y-axis, you need to get the current position by reading the Position of the Transform component (transform.position), then you set a new position by updating its new Vector3 position to its current X position (transform.position.x), clamping its Y position between -3.8f and 0. This is done by calling the function Mathf.Clamp, stating which axis (Y-axis) we want to clamp (transform.position.y) and between which values (its start position at 0 and -3.8f further down on the screen). The last 0 corresponds to the Z-axis, which stays at zero since we’re only concerned with working in a 2D space.
You could also clamp the Player movement in the horizontal (X-axis) between -11.3f and 11.3f, but this would be a bit boring. It would be much more interesting to have the Player object, upon reaching the left or right limits of the screen, reappear on the opposite side (think PacMan going through a tunnel).
In order to do this, you need to keep track of the Player object position in the X-axis (transform.position.x), and compare it to the desired limits. Once it has reached the edge of the screen and is no longer visible (at -11.3f on the X-axis), you then move it to the opposite edge at 11.3f (again on the X-axis). Whatever Y position is read (transform.position.y) will remain the same, while the Z-axis remains at 0.
Your script, once complete, should look like the following:
And there we have it. Please understand there is more than one method to script out these behaviors. Experiment and don’t forget to have fun :)