Skip to content

Implement a Splash Screen Using a Finite State Machine in Unity

Implementing a Finite State Machine Using C#

In this tutorial, we will implement a splash screen using a Finite State Machine in Unity. This is a continuation of the tutorial from Part 1. Here, we will apply the FSM that we created in Part 1 into a real Unity application.

Finite State Machine in Unity – Implement a Splash Screen

In this demonstration, we will create a simple one-way state machine to implement a splash screen.

The state diagram for our splash screen is given in the diagram below.

It starts with the FadeIn state where our logo is displayed gradually from completely transparent to a completely opaque state. After a certain amount of duration, it transits to the PlayAudio state where we play the Splash Audio. After the audio is completed we fade out the logo in FadeOut state from completely opaque to a completely transparent an exit the state machine.

Create the Unity Project

Create a new Unity 3d project and name it FSM or any other name that you fancy. Rename the default scene to FSMSplashScreen.

Create three folders in Assets called Audio, Scripts and Textures. Download the Sample Logo and the Sample Audio. Or if you have your own audio and image then you can use that as well.

Put the SampleLogo.png image in the Textures folder and the SampleAudio.wav audio in the Audio folder.

Convert the SampleLogo.png to a Sprite and then drag and drop into the scene. Reset the Transform to make set all the initial values to be at the origin with no rotation and unit scale.

1000

Adjust the camera position to be a 0, 0, -7 so that the whole sprite is visible.

Set the clear color for the camera to be black.

Scripts

Select the MainCamera and add a New Script component to it. Name the script to be SplashScreen.cs

Go to Assets and move this script to the Scripts folder. Double click on the SplashScreen.cs and open in your favorite editor. I prefer Visual Studio.

Add two variables. One for the sprite and one for the audio.

public GameObject spriteLogo; public AudioClip audioLogo;
Code language: C# (cs)

Now go to the Unity editor, select MainCamera and drag and drop the SampleLogo sprite to the Sprite Logo field in the SplashScreen script in the Inspector window.

Similarly, drag and drop the SampleAudio to the Audio Logo field.

Add a new component called AudioSource into the MainCamera.

The Finite State Machine

Create a file called FSM.cs and copy and paste the code that we created for our reusable FSM. We will use this State as the base class for our new concrete state classes associated with SplashScreen.

Looking at the state diagram we find that there are three states for splash screen. We represent their IDs as enumeration types.

/* * We create enums to represent the * unique ids of the different states. */ enum SplashStates { FADE_IN = 0, PLAY_AUDIO, FADE_OUT, }
Code language: C# (cs)

We will implement the concrete state classes in a moment. But before that let’s set up the necessary variables and implementations for the SplashScreen script.

Firstly, we will need a variable for the FSM. We then create a new instance of FSM and subsequently call the Update method of the FSM in the Update method of the MonoBehaviour script.

See below for the implementation.

public GameObject spriteLogo; public AudioClip audioLogo; /* * We create enums to represent the * unique ids of the different states. */ public enum SplashStates { FADE_IN = 0, PLAY_AUDIO, FADE_OUT, } private FSM m_fsm = new FSM(); // Start is called before the first frame update void Start() { /* * Create the three states and add * to the fsm. */ /* Set the current state (initial state) * of the FSM. */ } // Update is called once per frame void Update() { /* * We call the FSM update here */ if(m_fsm != null) { m_fsm.Update(); } }
Code language: C# (cs)

We will also add one more function which will be called when the FSM exits. Typically this will be handled by your game by either loading a new scene or to show some UI. For us, we will put up a Debug.Log.

/* * Exit function to handle the end of the FSM. */ public void Exit() { Debug.Log("Splash screen with FSM has exited."); m_fsm = null; }
Code language: C# (cs)

Well, we are almost done. Now, all we need are the actual states. Let’s implement them.

FadeIn and FadeOut States

Both these states have similar functionality which is to change the opacity of the sprite. In FadeIn we will go from 0 (completely transparent) to 1 (completely opaque) in a certain duration of time whereas in FadeOut we will go from 1 to 0 in another duration of time. So both these states can be represented by one class.

using System.Collections; using System.Collections.Generic; using UnityEngine; using Patterns; public class Fade : State { public float Duration { get; set; } = 2.0f; private float deltaTime = 0.0f; private FadeType m_fadeType; private SpriteRenderer m_spriteRenderer; private SplashScreen m_splash; public enum FadeType { FADE_IN, FADE_OUT, } public Fade(FSM fsm, SplashScreen splash, FadeType fadeType = FadeType.FADE_IN) : base(fsm) { m_splash = splash; m_spriteRenderer = splash.spriteLogo.GetComponent<SpriteRenderer>(); m_fadeType = fadeType; } public override void Enter() { deltaTime = Time.deltaTime; base.Enter(); switch (m_fadeType) { case FadeType.FADE_IN: Debug.Log("Entering: FadeIn State"); break; case FadeType.FADE_OUT: Debug.Log("Entering: FadeOut State"); break; } } public override void Update() { deltaTime += Time.deltaTime; if (deltaTime > Duration) { switch (m_fadeType) { case FadeType.FADE_IN: int nextid = (int)SplashScreen.SplashStates.PLAY_AUDIO; State nextState = m_fsm.GetState(nextid); m_fsm.SetCurrentState(nextState); break; case FadeType.FADE_OUT: m_splash.Exit(); break; } } if (m_spriteRenderer != null) { switch(m_fadeType) { case FadeType.FADE_IN: m_spriteRenderer.material.color = new Color(1.0f, 1.0f, 1.0f, deltaTime/Duration); break; case FadeType.FADE_OUT: m_spriteRenderer.material.color = new Color(1.0f, 1.0f, 1.0f, 1.0f - deltaTime/Duration); break; } } } }
Code language: C# (cs)

PlayAudio State

The second state in the splash screen application is the PlayAudio. In this state the AudioClip is played and the transits to the FadeOut state.

using System.Collections; using System.Collections.Generic; using UnityEngine; using Patterns; public class PlayAudio : State { public float Duration { get; set; } = 1.0f; private float deltaTime = 0.0f; private SplashScreen m_splash; public PlayAudio(FSM fsm, SplashScreen splash) : base(fsm) { m_splash = splash; } // lets discuss what generic functions need to be there in a State. public override void Enter() { deltaTime = Time.deltaTime; m_splash.GetComponent<AudioSource>().PlayOneShot(m_splash.audioLogo); base.Enter(); Debug.Log("Entering: PlayAudio State"); } public override void Update() { deltaTime += Time.deltaTime; if (deltaTime > 1.0f) { int nextId = (int)SplashScreen.SplashStates.FADE_OUT; State nextState = m_fsm.GetState(nextId); m_fsm.SetCurrentState(nextState); } } }
Code language: C# (cs)

Create these States and Add to the FSM

We will now create these states and add them to the FSM. We will also set the FadeIn state as the initial current state.

// Start is called before the first frame update void Start() { /* * Create the three states and add * to the fsm. */ m_fsm.Add((int)SplashStates.FADE_IN, new Fade(m_fsm, this)); m_fsm.Add((int)SplashStates.PLAY_AUDIO, new PlayAudio(m_fsm, this)); m_fsm.Add((int)SplashStates.FADE_OUT, new Fade(m_fsm, this, Fade.FadeType.FADE_OUT)); /* Set the current state (initial state) * of the FSM. */ m_fsm.SetCurrentState(m_fsm.GetState((int)SplashStates.FADE_IN)); }
Code language: C# (cs)

Save the scripts, save the scene and click Play in the Unity editor. You will see the splash screen transitions. Of course, the look from an artistic point of view is not there. But you get the idea.

Conclusion

In this tutorial, we have created a simple Splash Screen using the FSM that we created in Part 1. This is in no way the only way to create a Splash Screen. This is also perhaps not the best way to create a Splash Screen. However, this tutorial serves it well to see how we can use an FSM to implement simple UI in our game.


Proceed to Part 3 where we use the FSM and apply it to a complex Unity project which handles multiple animation states of a 3D animated character to create Player Controls. See a video of the example implementation.


Proceed to Part 4where we will use delegates to create a Finite State Machine. Thereafter we will demonstrate the use of the Finite State Machine by creating a simple key press based application in Unity.

Proceed to Part 5 where we will use the delegate based FSM created in Part 4 to create an enemy NPC behaviour that handles multiple animation states of a 3D animated character.

References

  1. https://en.wikipedia.org/wiki/Finite-state_machine
  2. https://gameprogrammingpatterns.com/state.html
  3. https://gamedevelopment.tutsplus.com/tutorials/finite-state-machines-theory-and-implementation–gamedev-11867

4 thoughts on “Implement a Splash Screen Using a Finite State Machine in Unity”

  1. Hello, I tried to follow this tutorial from Part 1.

    When I play, I got an error message:

    NullReferenceException: Object reference not set to an instance of an object
    GameDevelopment.FSM.Add (System.Int32 key, GameDevelopment.State state) (at Assets/Scripts/FSM.cs:50)
    GameDevelopment.SplashScreen.Start () (at Assets/Scripts/SplashScreen.cs:29)

    My namespace is GameDevelopment.
    FSM: 50: is the Add method (m_states.Add(key, state);)
    SplashScreen 29 : m_fsm.Add((int)SplashStates.FADE_IN, new Fade(m_fsm, this));

    SpashScreen is added to main camera with audio source.
    I have dragged logo and audio into the script.

    So I am not sure where I got wrong and am stuck in this tutorial for one hour.

    Appreciated your help.

    1. Hi Jimmy,

      A null pointer exception occurs if you are trying to access something that doesn’t exist. Chances are that you forgot to add a game object and trying to access it, or you may be you forgot to initialise the FSM.

      1. Thank you for your reply.

        I am sure I have added the gameobject. As to initiate the FSM, possibly….I am not sure if I did since I had no idea “where” to initialise FSM.

        As this is new concept to me (I am new to programming), I am reading up to understand more about FSM. Will come back and “test” again once I understand more how the codes work (and then can upgrade to part 3). As to the general idea of FSM, I got it already.

        Thanks again for your tutoiral.

Leave a Reply

Your email address will not be published.