To all my fellow Americans, I hope you enjoyed yourself a safe and happy Thanksgiving. And to all the readers across the globe, I encourage you to take a moment to be thankful for everything you have in your life and to spend some extra time with those who matter most to you.

I am so thankful for all of you reading, and I am excited to talk about making video games with you all today – so lets get into it!

In the Unity game engine, most things that we interact with are special classes inheriting from the Unity class called “Object.” The Object class is different than the standard C# Object class in the System namespace, and allows us to interact with that particular object in the Unity editor.

In most cases, when we create something we want to interact with in Unity, we will not be inheriting directly from the Object class, rather we most often will create a class that inherits from MonoBehaviour, Component, or ScriptableObject, that in turn inherit from Object.

Over the next few Feature Friday articles, we will be discussing these custom classes – what they are, how to use them, and the hidden features you never knew about. To kick things off, we’re going to start with the one is probably used most often: the MonoBehaviour class. 

Oh and be sure to read all the way to the end of the article where I feature an awesome video made by Andre from Mix and Jam!

1. The MonoBehaviour Lifecycle

Video games are a type of software application that have both event based and update based logic.

Event based logic means that when some specific input is triggered, some set of actions occur. Think about a game with health pick-ups. When a player comes in contact with a health pick-up, an event is triggered that removes the health pick-up from the game world and adds it to the player’s inventory.

Update based means that the application is checking for certain conditions or performing actions on a regular interval. An example of the former would be to have a game regularly check if there are any enemies within a certain range of a player. An example of the latter would be to move a player from Point A to Point B over a set amount of time.

In the Unity Game Engine, the MonoBehaviour class allows us to take advantage of both event and updated based logic when programming our games. When we create a new C# script in Unity, by default it will inherit from MonoBehaviour and define an event based method and an update based method (Start() and Update() respectively).

public class Player : MonoBehaviour
    // Start is called before the first frame update
    void Start(){}

    // Update is called once per frame
    void Update(){}

Taking a look at the comments before each of the classes gives us some insight into when these methods are called. Note that we typically do not call the Start() or Update() methods directly, That is all handled internally by Unity.

And from this, we can start to get the sense that our MonoBehaviour scripts have some sort of lifecycle that determines when these functions are triggered. Now you can see that the Start() method is called once when the MonoBehaviour is first initialized, however there are actually two other event functions that are called before the Start() function.

The Awake() function is ran at the very beginning of script initialization and will only ever be ran once per instance of the script. I typically use the Awake() function to get references to other components on this GameObject, or set values local to this MonoBehaviour class.

This is because when our game starts running, ALL Awake() functions will be ran before any other class runs their Start() functions. In the Start() function, this is when I will have my code reach out to other GameObjects and components to set their references.

The other function that is called before start is the OnEnable() function, and this one can be ran multiple times per instance of the script. It is always called once at initialization – after Awake() and before Start() – but it is also called each time the class is re-enabled after being disabled (more on this later).

Once the initialization functions have been ran, now the MonoBehaviour is ready to start to do things in our game; and in most games, this requires input or output to be ran on a regular interval – enter update functions.

There are three main types of update functions built-in to MonoBehaviours: Update()FixedUpdate(), and LateUpdate(). Each of these functions will be constantly ran at consistent intervals while the MonoBehaviour is alive and enabled in our game – this is why it is generally a good idea to avoid running performance heavy code within every call to these update functions.

The Update() function is called once per every frame rendered to the screen – so if your game is running at 60FPS, that means that the Update() function is being ran 60 times every second on every single active MonoBehaviour instance in your game, throughout the entire duration of your game!

The LateUpdate() function is called on the same interval (once per frame), however it is ran after all other Update() functions have completed and before the current frame is rendered. I use this mostly to update the position of cameras that follow moving objects. This ensures that the object is in its final position for that frame, before adjusting the camera to look at the object – not the other way around.

FixedUpdate() is a bit different because it is ran on a fixed time interval. Games in Unity are typically ran at a variable frame rate – meaning that the game will run at as high of a frame rate as it can. This is great, but it can mean that the frame rate adjusts over time and it isn’t always locked at one specific frame rate. So it is not typically a good idea to move things in a regular Update() function because objects may move at different speeds depending on the frame rate the game is running at.

FixedUpdate() solves this problem by running it at a fixed time interval (0.02 seconds or 50 times per second by default). This means that you can reliably have accurate behavior over time, regardless of what device you are running on and what frame rate is capable.

Note: depending on the frame rate of your game, FixedUpdate() may run more or less often than the Update() function.

So now that we have covered initializing and running MonoBehaviours, the final component is decommissioning them once we are done with them. There are also three decommissioning events: OnApplicationQuit()OnDisable(), and OnDestroy() which are all ran in that order.

OnApplicationQuit() is ran only when the entire application running your game is closed.

OnDisable(), the counterpart of OnEnable(), can also be ran multiple times throughout the lifetime of a MonoBehaviour. OnDisable() is ran when the MonoBehaviour or GameObject is attached to is disabled through code or via the check box in the Unity Inspector window.

Click here to read the Feature Friday article on Inspector windows.

Finally OnDestroy() is called when the GameObject this MonoBehaviour is attached to is destroyed through a number of ways. The GameObject can be destroyed by calling the Destroy() method directly (passing in a reference to the GameObject you wish to destroy), by loading a new scene, or by closing the application.

In general it is not a good idea to instantiate any new objects from any of the decommissioning events. For example if your OnDestroy() function spawns two more objects, then every time you exit Play Mode in the Unity editor, instances of those two objects will be spawned for every instance of the MonoBehaviour in your scene. This is likely going to be an unwanted behavior for you and the number these objects can add up quickly.

So that is the basic lifecycle of a MonoBehaviour – it is instantiated and initialized, then it frequently receives updates to handle game logic, and finally it is cleaned up in the decommissioning phase. However there are many other events built-in to MonoBehaviours that are extremely useful to know.

Reference this document for the full execution order of the MonoBehaviour lifecycle:

2. Unique Events in MonoBehaviours

Other than the standard lifecycle events, the physics events are the most commonly used. These come in the form of OnCollisionEnter()OnCollisionStay(), and OnCollisionExit(). These events also have OnTriggerXXX() and 2D() equivalents.

The physics Enter() functions are called on the first frame two objects intersect or collide with each other. The Stay() functions are called every FixedUpdate() step that the objects are in contact with each other. The Exit() functions are called on the first frame the objects are no longer touching one another.

If you’re curious about how these fit into the MonoBehaviour lifecycle, these functions are ran towards the end of the FixedUpdate() step – after FixedUpdate() and the fixed animation updates. The OnTrigger events get ran before the OnCollision events.

And finally, at the very end of the FixedUpdate() step, any coroutines yielding on “WaitForFixedUpdate” will resume execution.

As an aside, coroutines yielding on “null” and “WaitForSeconds” will resume execution immediately after the Update() function but before the animation update. Coroutines yielding on “WaitForEndOfFrame” run at the very end of the lifecycle, after the current frame has been rendered internally, but before it is displayed on the screen.

Note: If you would like an overview on coroutines, please read last week’s Feature Friday on coroutines.

And speaking of coroutines, many of these event functions can be inherently used as coroutines. Let me show you what I mean. Let’s take a look at the Start() function, if we wanted to delay execution of a portion of the function, we could do something like this:

private IEnumerator Start(){
    Debug.Log("Initializing Object");
    yield return new WaitForSeconds(1f);
    Debug.Log("1 second after initialization");

Notice how instead of our Start() function returning void, it returns an IEnumerator, just like a coroutine. The Start() coroutine is instantiated automatically at the time it would begin if it were a standard function.

Another useful event function to be aware of is the OnValidate() function. This one is called when a value is changed in the Unity editor. It is useful because it allows you to do some well, validation, to confirm that all your values are in expected ranges and that objects are being properly setup in the editor.

The last two event functions I have to share with you today are OnBecameVisible() and OnBecameInvisible(). These two events get fired on the frame that the renderer attached to the GameObject this MonoBehaviour is on goes in or out of view of any camera. These functions can be used to disable certain components when the object is out of view of the camera for better performance.

But that is far from all the available event functions available in MonoBehaviours. Feel free to peruse the Unity documentation to find what other events are available:

3. Properties of MonoBehaviours

The MonoBehaviour class inherits a few properties from other Unity base classes. These properties are mostly used on MonoBehaviours so it makes sense to talk about them here. You likely have seen most of these if you’ve done some programming in Unity but I did just want to run through them real quickly.

  • enabled – Gets or sets the MonoBehaviour’s enabled state. MonoBehaviours that are not enabled, will not be updated
  • isActiveAndEnabled – Checks to see if the MonoBehaviour is enabled and if the GameObject it is attached to is active in the game world
  • gameObject – Returns the GameObject the MonoBehaviour is attached to
  • tag – Returns that tag string the GameObject this script is on
  • transform – Returns the transform component of the GameObject the script is on
  • hideFlags – Gets or sets the HideFlags on the GameObject
  • name – Returns the name of GameObject the script is on

The one interesting one I do want to spend some more time on is the hideFlags property. The hideFlags property gets or sets the HideFlags enum associated with the GameObject the script is attached to. HideFlags can be set to one of the following options:

  • None – Normal visible object, default
  • HideInHierarchy – Object will not show in hierarchy
  • HideInInspector – Object cannot be viewed in the inspector
  • DontSaveInEditor – Object will not be saved to the scene in the editor
  • NotEditable – Object will not be editable in the editor
  • DontSaveInBuild – Object will not be saved when building the game
  • DontUnloadUnusedAsset – Object will not be unloaded by Resources.UnloadedUnusedAssets
  • DontSave – Combines DontSaveInBuild, DontSaveInEditor, and DontUnloadUnusedAsset
  • HideAndDontSave – Combines HideInHierarchy and DontSave

In general, you’ll just want to stick with the default of HideFlags.None, but there are some instances where setting the hide flags would be valuable to use. This would most commonly be used for custom tooling helpers where you wouldn’t want someone on your team incidentally messing with an object that could break some things with your custom tooling.

Featured Unity Tutorial of the Week: Mario Galaxy’s Launch Star – Mix and Jam

Today’s featured tutorial comes from Andre from the Mix and Jam YouTube channel. Andre’s channel is all about recreating well know effects and mechanics from popular video games.

One of my favorite games is Super Mario Galaxy on the Nintendo Wii – one of the main mechanics of that game is using the launch stars to propel yourself from planet to planet. Andre shows in this video exactly how to accomplish that effect in the Unity game engine.

It’s actually easier than you might think, so go check out the video, and follow along! And be sure to check out the other videos on the Mix and Jam YouTube channel, they are really great.

Mario Galaxy’s Star Launch:

I know this week’s Feature Friday may be a bit of a refresher for many of you, but I do think that it is important to go over the basics to ensure we are all on the same page before moving in to more complex topics.

Pre usual, if you do have any suggestions for Feature Friday topics or games/tutorials made with Unity, feel free to let me know by replying to this message.

Anyways I hope you are all staying well, and as always, keep on creating!

-Johnny Thompson
Turbo Makes Games