Unity Nuances

During my time using Unity I have had to adapt some of my normal C# knowledge, working with Backend Systems mostly to how Unity structures its scripts and some of the nuances involved. So I thought I would write some of them down here, mostly so I can look back and remember if I run into a barrier!

Coroutines or Async?

Coroutines

I’m very used to using async/await with normal C# however with Unity I found that another feature that is ‘native’ to Unity which is Coroutines. Coroutines are useful if you want code that can be executed over multiple frames, the moment you use yield return inside the coroutine, you essentially pause and give control back to the Unity Engine. This is great for instances where you would for example, need logic such as moving a bird across a screen to occur.

// In Update 
if (Input.GetKey(KeyCode.Space) && canPlayerJump)
                StartCoroutine(PlayerJump());
private IEnumerator PlayerJump()
        {
            canPlayerJump = false;
            // jumpTime initialised to something like 0.5f
            for (float jt = jumpTime; jt >= 0; jt -= Time.deltaTime)
            {
                transform.Translate(0, Time.deltaTime * 10, 0);
                yield return null;
            }

            canPlayerJump = true;
        }

In this example code we are checking to see if the player is trying to jump with Spacebar and if they can, once these requirements are met it will invoke the Coroutine which will flag the player as unable to jump and enter a for loop, which will run until our jumpTime has been set to 0. Within this loop, is some code to translate our position on the y-axis and then to yield. The next frame will pick up from the yield and ensure the for-loop continues until it can fulfil its criteria. At which point the canPlayerJump boolean is set to true and the coroutine exits.

Async

Async however to my understanding is a native C# feature which allows for our code to run ‘synchronously’. It is synchronous not in the sense that a new thread is created when we await a function, but that in the time that we begin to await and the logic of our frame is being completed, control can be returned to the point it was invoked and the remaining logic executed.

If you have a keen eye you will have noticed that while a Coroutine releases its control to Unity Engine, thereby waiting for the next frame to continue, async/await once finished will simply carry on and control will be returned. This can be tested by having some logic in the Awake() section of a script, take turns invoking a Coroutine and an Async method and getting the current frame before and after, in my case the Coroutine would always go from 0 -> 1 whilst the Async method would wrap up within the same frame.

Taking from a Unity Conference, there was also a mention of potential memory leaks due to how Unity handles Coroutines, stating that if the scripts parent object is removed before finishing, there are cases where code releasing memory cannot be executed. Source: Johannes Ahvenniemi, Seriously Digital Entertainment - Unite Copenhagen 2017

In summary, from what I have found each has their use-cases and implications whilst using them; it is not wise to assume they are two types of the same tool.

Handling JSON

This annoyed me greatly, needing to use the JsonUtility library I was baffled when I had set up my models to fit the expected JSON, to find that it simply would not deserialize - no errors, just a null object.

var deserializedObject = JsonUtility.FromJson<RootObject>(json);

This was strange yet stranger still, creating a variable of RootObject and providing values for the fields I was hoping to retrieve and trying to convert them to JSON would result in an empty string.

The problem? Unity failed to highlight that they do not like using properties and will only allow for using normal fields. In other words using public string MyString {get; set;} is a big no-no.

Luckily I used properties out of habit more than requirement, however if you run into this and absolutely must use properties I would suggest looking into getting Unitys Newtonsoft package.

Handling GameObjects as their Classes

I feel like this is probably obvious, but I’m going to talk about it anyway.

I found myself in a scenario where I wanted to have a prefab, and a list of those prefabs put into a buffer upon instantiation so that I could create a FIFO continuously instantiating system. My first problem was by using GameObject, I needed to be able to invoke methods on these objects who as far as the computer was concerned - was of type GameObject and certainly did not have any of the methods I was looking for.

Simple fix, ensure the type of the prefab and type the list will contain are the prefabs script type. However I tripped up when the objects would remove from the buffer but would not be deleted from the scene which would be an awful bug if I didn’t catch it. Turns out when making that change I needed to use ObjectType.gameObject as the Destroy parameter.

Simple but lesson learned, I suppose.