Unity Engine is a wonderful tool for game creation. Many games like Asteroids, Super Mario, Pong and even E.T. use user inputs to move the main character.
In this story, I will go on multiple ways to move an object and tie it to Unity Input. (A story for Input System is coming)
You may leave a comment if something unclear.
In a new scene, we add a simple cube. We can move it with the editor Move Tool. This is useful to place an object in the scene, but the object will not move in Play Mode.
You may move it manually in the Scene view Window. However, the user will not have access to this window during normal gameplay.
To move the character/cube/player (Will be called Player Object from now on) game object, we will need to create a new script that will alter the current position. To do so, we will need to access the Transform component.
Let start with a component that defines the behaviour of a GameObject. Every GameObject in Unity has a Transform component.
There are 3 parameters in this component.
Position, Rotation and Scale.
To move an object we will only use the first parameter Position.
Position represents the current 3D position relative to the parent space. (I will get back on Local and World Space.)
Moving with script
To move an object with a script you have two main choices that are built-in the editor. Using a Translation or RigidBody Velocity.
We will first need to create a new C# Script. I will name it SimpleMovements.
Note: You can also use visual scripting. The nodes should have a similar name as functions used in this story. However, this story is entirely focuses on C# scripting.
Attaching script to a GameObject
Once the script is created, you can Drag&Drop the script on the object or on the Inspector window of the object.
Note: Unity will automatically add some basic code to be able to add it to a GameObject. Shuch as the interface MonoBehaviour which is absolutely needed to be attached to a GameObject. This is specific to Unity Engine.
Opening the script
With the script attached, we can open it in our preferred code editor. Once open we should see the default Unity script.
Note: The class has the EXACT SAME NAME as the file. (Minus the file extension .cs) It is required that the script file is the same as a MonoBehaviour class. If they are not the same, Unity will throw and error message at compile time.
Set Position (Read First)
So, to move a character with the script we need to alter its position. Let’s start by accessing the Transform component of our player object.
Since Transform is mandatory for all GameObject we don’t need to search for it. It is already cached by the name transform with a lowercase “t”.
Note: That Transform with an uppercase “T” is the class and transform with a lowercase “t” is the cached component.
Also, Cached component means that you can access it with a reference variable. Which means you don’t need to search it everytime you need it.
If you don’t have a reference to the component you need, you can either use GetComponent or reference it with by Drag&Drop on an exposed reference variable in the Unity Inspector (More on that on a future Story).
Let’s type in the Unity default function that is void Update(): transform.
If you put the period “.” at the end, we can see the auto-complete giving us multiple suggestions. (If your IDE offers you this feature. I use Visual Studio)
We can see the choice of position is there.
From there we can add position. position is a public Vector3 variable. Which means we can set it with “=”. We need to make it equal to a Vector3. We can either use a predefine Vector3 like Vector3.zero, .right or .one. Or create a new Vector3 like so.
In these 3 examples, we can see that in play mode, the cube moves to the position marked in the code.
However, we can see the cube is not “moving”. It is instantly teleported to its destination.
It may have some use case, but not for the current goal. Let’s make it more
Note: The 3D coordinates are XYZ. Also Unity’s UP axis is Y. It may be different than 3D modeling software like Blender.
Now we know how to alter the position, let’s see how to making it move less instantly.
Note: When using anything with Physics and precise position like player movement. Always use FixedUpdate and DeltaTime.
Without explaining it : Update is frame rate dependant = inconcistent.
FixedUpdate is ”””Time””” depedent = concistent.
Instead of setting the position, let’s add instead!
Looking nice, but it is really fast. We can reduce it to 0.1f, but first, we can make it time-related by multiplying each coordinate by Time.DeltaTime.
By adding Time.DeltaTime make it smoother and slower.
Let’s make the new Vector3 into a variable that we expose in the editor.
Now let’s talk SPACE!
Without going too deep into the subject, in Unity Editor there are two coordinate systems. Local (Self) and World.
Self Space = Applies transformation relative to the local coordinate system.
It bases the change on itself. Considering the object rotation.
World Space = Applies transformation relative to the world coordinate system. It will not consider the object rotation. Also, if the object has a parent object, the parent is the world for the child. To have an absolute world position, try subtracting the parent coordinates.
In the current example, we are using position, which is World space.
If you want to use a local you need to change position by localPosition.
Alternatively, you can use the function transform.Translate. You can replace this:
transform.position += speed3 * Time.deltaTime;
transform.Translate(speed3 * Time.deltaTime, Space.World);
You just need to change Space.World to Space.Self to change the coordinate system.
Translate is essentially the same as “transform.position +=”, but take a Space parameter. Also, it is Self by default.
Using Unity Input
To control the character with keyboard input, we can use the default Unity Input. (Will be replaced by Input System — GamePad and more)
Using Input.GetAxis we can get the current value of WASD and Arrows.
We simply need to multiply the input by the speed and Time.DeltaTime.
We get a smooth movement because of the DeltaTime and FixedUpdate.
The reason why it is working is that the axis returns 0 if not input is pressed. The result is then 0, meaning no movement. If the axis is pressed it returns 1 to be multiplied by the speed.
Bonus — Mouse position
Here a little bonus. If we keep the teleportation behaviour, we can use the mouse location as a destination. Since this story is meant to be simple I will not explain Raycasting here, but here is how to get the mouse position at collision with a collider.
This is really useful for things like a placeholder in games like a tower defence.