Frame Update & Movement in Unity

Paul Marsh
4 min readApr 10, 2021

--

One of the fundamental requirements of any Unity application is to receive input. For example, consider just moving a simple character in a 2D game. You want to move it left/right/up/down.

Classic Unity Input Method

The classic way to write a horizontal movement in Unity would be something like this;

It’s really easy to write and really easy to read, however it does have a couple of problems. Firstly it is using the ‘old input system’ which although is fine for a lot needs it has been superseded by the cunningly named ‘Input System Package (New)’

This allows for a much cleaner separation of input hardware to resulting action. But realistically from a code point of view it just means the code is slightly altered.

Performance

The second problem is performance. As you may have read the Update() method is called once per frame. If you have a number of GameObjects (not absolutely correct but think of it as entities under the control of Unity), then if each one has an Update() method then Unity will have to run that code for each instance of each game object for every frame. In the title image for this article you can see 400 cubes each with their own Update() method responding to keyboard input. In a system where Frames Per Second (FPS) is important for smooth interactions then any work that is carried out per frame will have a negative effect. In our current code we could mitigate the cost of the update by optimizing the code in the input, for example we might chose to only Translate if we have detected a movement. Whilst any reduction in the cost of the Update() is welcome the fundamental problem remains, if Unity detects the Update() method is on the entity then it will be forced to execute it and wait for the result. Is there a way to avoid this?

Events

The theory is that if we remove the Update() method then we remove the need for Unity to evaluate it on each frame, therefore Unity can process more frames in a second. The previous code examples are using a ‘Polling pattern’, i.e. every time they run they ask the Input system for the values. Is there a way we can get the Input system to tell us when the user is doing something, and therefore only evaluate the movement for frames when movement is being requested?

With the ‘new’ input system there is a potential “yes”;

The InputAction allows you to map hardware input to certain types of values/actions. In the above example a 2D vector is produced when the user selects any of the defined navigation keys, e.g. WASD. What we are really interested in here is that it has a number of events. The naming of the events is a little odd, so imagine you are playing a game and have made the following key strokes; Held ‘A’ for 2 seconds and then added holding ‘W’ for 1 second and then released both keys. The output from the above would look like;

started
performed
performed
canceled

For me ‘performed’ is a little bit confusing, but the important take-away is an interaction is bounded by ‘started’ and ‘canceled’. We now have a means of being told when we should examine the input, but how do we keep processing the input if we are not using an Update() method?

Coroutines

Coroutines are a slightly odd feature of Unity. My view is that there role is to create a block of code whose lifetime is dynamic. What a Coroutine is NOT is a separate thread of execution. If you look at the Unity execution order then you see that Unity executes Coroutines in sequential order with all the other code it needs to evaluate. I have highlighted some of the Coroutine execution points in the following snippet;

If it is still executed on Unity’s main thread, then what is the advantage? In this case the advantages is that we can create something akin to a dynamically living Update() method. I.e. when we receive an event to tell use the user is requesting a move then we can dynamically create a method to handle the movement. When we receive the event to tell us the user has stopped the move we can remove our dynamic Update() method and Unity will not have to keep evaluating it.

NB Always ensure any Coroutine with a tight loop is stopped when the object is disabled/destroyed

Caveat

Okay, so we have a nice solution to stop Update being continually evaluated but we have introduced the overhead of consuming a couple of events and processing Coroutines. In some cases this is certainly worth the effort, but as with almost everything in code, “it depends”. For example, if this is for a hectic high speed scrolling shoot-em-up then it’s likely the user will almost always be needing movement. In that case just having a simple Update() method would make more sense. Whilst this Event/Coroutine alternative is a useful tool to have in your virtual toolbox, always remember to performance test your application to know what is best for your specific situation.

--

--

Paul Marsh
Paul Marsh

Written by Paul Marsh

Unity, VR, Enterprise and .Net Developer

No responses yet