A Game Design Tip a Day #8 – [Unity C#] Coroutines (Part 1)

Unity has a cool feature (I’m not a nerd at all) that lets you run a function over various frames without using some clunky method that’s difficult to write and long as hell. Coroutines are special kinds of method that, together with the yield keyword, can be used to suspend the execution of one call to a function temporarily – this allows it to run over several frames. Well, they’re much more complex than that, but I’ll be going into more detail in another tip at some later date. One great thing about coroutines is that they’re run in the same thread as all your other MonoBehaviour stuff (like Start or Update), so there’s no problems to worry about with regards to messing with the same variable in both Update and a coroutine, for example. They also have minimal overhead while providing huge amounts of functionality.

Coroutines in C# have a return type of IEnumerator:

tip_a_day_08

This coroutine does… absolutely nothing at all, but it’s just here to show you the basic structure of one. Firstly, every coroutine needs a yield statement somewhere in it, or else it will fail to run. In this example, yield return null will cause the coroutine to wait until just after the next Update() method is called. Coroutines also need to be called in a special way – we use the StartCoroutine() method, which has many overloads:

tip_a_day_08_02

The three uses of StartCoroutine in the Start method are all valid ways of calling a coroutine. For coroutines that have more than one parameter, you’ll want to use the third version. There’s also a StopCoroutine(“MyCoroutineName”) method that can be used on any coroutine that was called using one of the string-based StartCoroutine functions, which will tell a coroutine to cease execution forever. Like coroutine murder, with less blood. Unfortunately, that does mean that any coroutines that have more than one parameter can’t be stopped in this way.

There are many other kinds of yield statements you can use, too. Rather than always using yield return null and just waiting for the next Update frame to finish, there’s tons of other yield statements in your coroutine goodie bag:

tip_a_day_08_03

Some of these are very interesting (to reiterate, I’m definitely not a nerd). I’ve listed many of their effects above, and they’re all pretty straightforward. I’ve never really used WWW before, so I can’t claim to know how they work in much detail, but it seems they wait until some WWW download has finished before doing what yield return null does. The next one, yield return StartCoroutine(SomeCoroutine(someParameter)) is an extremely useful coroutine feature that suspends this current coroutine until another one has finished execution. I can even put a similar statement in the second one to wait for a third coroutine – this is called coroutine chaining. Just be careful that you don’t create a circular chain of coroutines that call each other, or things will get very ugly very quickly. You’ll want to be careful when some of these because they run in a specific order – for example, a WaitForSeconds always runs before a WWW. Consult Unity’s Execution Order of Event Functions manual page for more info – the diagram at the bottom of the page should be ingrained in your memory by now.

I’ll be wrapping up some other coroutine features in another tip some day, but for now I’ll leave you guys to play around with these ones.

A Game Design Tip a Day #7 – [Unity C#] Prettier Variables in the Inspector

Spaced Out

When you have a script with tons of different variables, more often than not you’ll just end up with a huge list of variables and it’ll get tedious trying to find the variables you want to change in the Inspector. There’s an easy way to remove this frustration – use the Header and Space attributes.

The ‘Header’ attribute is used to give a subtitle to groups of variables in the Inspector. Its syntax is [Header(name)], where name is a string of your choice which will act as the header. The ‘Space’ attribute can also help with organisation, as it leaves a small gap between variables in the Inspector. It’s used much the same as Header, except it’s given an integer parameter which tells the Inspector how many pixels high the gap should be. The syntax for Space is [Space(height)].

This is what a script looks like in the Inspector without any of these special attributes:

tip_a_day_07
Imagine this list of variables, except too big to fit on a screen. Welcome to Unity.

As you can see, it’s not terribly useful for all these variables to be so close together. It’s far worse when you have about fifty bloody variables with loads of different types and tons of different functions, at which point it becomes impossible to find where you’re supposed to modify values or assign game objects. In this example, it’d look much cleaner if we separated the attack variables from the rest and gave it a header. And that’s just what we’ll do:

tip_a_day_07_02
I’ve always wanted to be able to find variables in the Inspector. I swear, one day I’ll be able to.

This makes things very slightly neater than before. I’ve used Space to separate the ‘script’ parameter from the rest, and a Header to highlight the attack variables more clearly. Header provides a small amount of space on its own, so I didn’t need to worry about leaving a space above the header.

Bounding your variables

In this example, there’s something else we can do to make the designers’ lives easier and make things less likely to break due to human error. Imagine the example script above is to be attached to a player, and that ‘health’ is the player’s maximum health. Well, it probably has an upper limit, and it wouldn’t make too much sense for it to be negative, so we can use the Range attribute, with the syntax [Range(x, y)] (where x is the lower bound and y is the upper bound, both inclusive), to fix variables modified in the Inspector between two values.

tip_a_day_07_03
Sliders instantly make this 70% cooler. But I’m pretty sure Sliders Inc. paid me to say that.

This makes the values in the Inspector gain these neat little sliders too, which allows for a much more obvious representation of how large or small your variable’s value is compared to its maximum and minimum. Obviously Range can only be applied to variables of certain types – it wouldn’t make any sense applied to, say, an AudioClip – so make sure you only try using it with numerical types you can actually give a range to. Be careful in your code too – Range only impacts what you can set the variable as in the Inspector and doesn’t stop you freely changing it in code beyond Range’s, uh, range. However, it does make things tons easier for the designer since they won’t need to delve into the code to see any intended restrictions on what the variables’ values should be. And it seemingly has the nice effect of making your code twice as long.

This rounds up the first week’s worth of AGDTAD! I have plenty of ideas to continue the series (many A4 sheets were harmed in the making of this), so be sure to stay tuned for more funky and wacky ways to use Unity and other general game design tips! If you’re enjoying the series so far, be sure to share it with your friends and leave a comment if you want me to cover a certain area of game design in more detail.