Applying a Finite State Machine Using C# in Unity to Implement a Splash Screen

Applying a Finite State Machine Using C# in Unity to Implement a Splash Screen

This tutorial first appeared in Faramira

In this tutorial, we will learn how to apply a Finite State Machines using C# in Unity.

This is Part 2 of the tutorial. It uses the Finite State Machine created in Part 1 and applies to a Unity project in a simple straightforward UI implementation of a Splash Screen.


Applying the Finite State Machine to Create a Splash Screen in Unity

This is a continuation of the tutorial from Part 1. If you have not read Part 1 of this tutorial then I strongly suggest that you read Part 1 first. In this Part 2 of the tutorial, 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 the first 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.

No alt text provided for this image

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.

No alt text provided for this image

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

Set the Clear Colour for the camera to be black.

No alt text provided for this image

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 favourite editor. I prefer Visual Studio.

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

public GameObject spriteLogo;
public AudioClip audioLogo;

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.

No alt text provided for this image


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,
}

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();
    }
}

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;
}

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;
            }
        }
    }
}

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);
        }
    }
}

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));
    }

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 earlier. 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.

In Part 3 of our Finite State Machine tutorial, I will demonstrate the use of the same Finite State Machine and apply to a complex Unity project which 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

要查看或添加评论,请登录

Shamim Akhtar的更多文章

  • Implement Mazes in Unity

    Implement Mazes in Unity

    This tutorial will show how to implement mazes in Unity by applying the backtracking algorithm with an explicit stack…

  • Reusable Finite State Machine using C++

    Reusable Finite State Machine using C++

    This tutorial will implement a reusable Finite State Machine using C++. We will then illustrate the concept by applying…

  • Enemy Behaviour Using C# Delegates in Unity

    Enemy Behaviour Using C# Delegates in Unity

    In this tutorial, we will implement enemy behaviour with Finite State Machine using C# delegates in Unity. This is a…

  • Finite State Machine Using C# Delegates in Unity

    Finite State Machine Using C# Delegates in Unity

    In this tutorial, we will implement a Finite State Machine using C# Delegates in Unity. We will then demonstrate the…

  • CPF Simulator

    CPF Simulator

    Recently, as an experiment, I had written a CPF Simulator to compare and contrast the various amounts that you can…

    2 条评论
  • Solving 8 puzzle problem using A* star search

    Solving 8 puzzle problem using A* star search

    In this tutorial, we will solve the 8 puzzle problem using A* (star) search algorithm. We will approach the solution by…

  • Implementing a Finite State Machine Using C# in Unity — Part 1

    Implementing a Finite State Machine Using C# in Unity — Part 1

    In this tutorial, we will learn about Finite State Machines and implement a Finite State Machine using C# in Unity. We…

  • Artists Own the Industry Now!

    Artists Own the Industry Now!

    Do you remember the last time an artist or a song that really captured your mind and your heart? What was that…

  • The Myth of the “Tortured Artist”

    The Myth of the “Tortured Artist”

    The Myth of the “Tortured Artist”. Throughout history, one common thread in the mystery and allure of the artist is the…

    1 条评论
  • Forex Trading – 3 Embarrassing Truth Revealed

    Forex Trading – 3 Embarrassing Truth Revealed

    This article appeared first on faramira.com.

社区洞察

其他会员也浏览了