Ok… so, this may be my first Unity only related post. I’ve been using Unity for quite a while, but I have never really posted anything about it code related, mostly just demo’s. So, along with the new year we have a new subject to write about… Yay!
So, for my Unity coding debut I have a nice n’ simple script that turns on/off Game Objects in sequence – useful for Construction Sequences. It also has a UI with play/pause/previous/next buttons. “Wow…Buttons!” you say?!? Ha, I know this isn’t too impressive, but you could use this as the base of something more, or you are really new to Unity and C# and need an example to work through. Well, whatever your reasons for reading this, I shall share how it’s done…
Demo…
So you know what the hell I’m talking about, here is a short demo video…
See… I did tell you it wasn’t anything amazing, but just like the half dead batteries, arbitrary fuses and the xmas cracker torch/micro-screwdriver I have in “man draw”, there will probably be a time in the distant future they might be useful… you know, that time that the TV remote batteries die at exactly the same time a freak power surge blows the lamp fuse and the screws fall out on your reading glasses… apocalypse level simultaneous catastrophic failure… I am the indoors Ray Mears… Where was I? Oh yeah, the setup…
Setup…
I will briefly walk through how to set this up yourself. It only takes a few minutes to get up and running, although, if you are new to C#, I would highly recommend (like all code on this site) to type in full yourself instead of copy and paste… just helps you along the learning curve that bit faster in my opinion…
Unity Editor…
In the Scene Hierarchy in the Unity Editor I created a Canvas with an empty child Game Object I have named UI_SqncCtrls…

You can see from the above image I have added 5 child Game Objects under the UI_SqncCtrls Game Object which I have listed below (which I have inadvertently made look like a recipe – I haven’t had dinner yet)…
- 1 Image – As the Background to my buttons that I have set to a transparent grey.
- 4 Buttons – As the playback controls. I have removed the child Text Game Objects as I don’t need text on the buttons and I also changed the default sprite to some icons I liberated from the interwebz – but you can do your own thang.
NOTE: The names of the Button Game Objects are important, if you do use your own naming convention, be sure to make the change the names in the script below.
This is what mine looks like (yours may differ depending on how you set it up – but should look similar enough, hopefully)…

NOTE: The Play and Pause Buttons are in the exact same location, but I have turned off the visibility of the Pause Button in the inspector like so…

We’ll handle the pause/play button visibility in code, but I still like to turn off the visibility by default in editor. Now onto the main part…
Code…
On the UI_SqncCtrls Game Object, I created a new C# Script named SequenceController which I will use to do all the heavy lifting. This manages the visibility of the buttons and the Game Objects in the Sequence.
Here is the class I created to make this work. This is easy enough that I think even a complete NOOB in C# could follow…
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SequenceController : MonoBehaviour
{
[Header("Sequence Controller")]
[Tooltip("Drag in a bunch of GameObject you want in the sequence (must be in correct order before dragging in).")]
/// <summary>
/// List of GameObjects in sequence (must be in correct order)
/// </summary>
public List<GameObject> SequenceItems;
[Tooltip("The amount of time in seconds between sequence items.")]
/// <summary>
/// The interval of time in seconds between sequences.
/// </summary>
public float sequenceIntervalDelay = 2f;
private Button _playBtn;
private Button _pauseBtn;
private Button _prevBtn;
private Button _nextBtn;
private int _currentIndex;
/// <summary>
/// The current sequence index.
/// </summary>
public int CurrentIndex
{
get { return _currentIndex; }
set
{
if (value != _currentIndex)
{
// Ensure current index isn't more/less than the index bounds of the given Sequence Items...
if (_currentIndex >= 0 || _currentIndex <= SequenceItems.Count - 1)
{
_currentIndex = value;
}
}
}
}
/// <summary>
/// Get things ready before first update occurs.
/// </summary>
void Start()
{
// Ensure Sequence is reset and only the first Sequence Item is visible...
ResetSequence();
// AddListeners to UI Controls...
SubscribeToUIControls();
// At start ensure Pause Button is hidden...
_pauseBtn.gameObject.SetActive(false);
}
/// <summary>
/// Get the UI controls from transform and add listeners.
/// </summary>
private void SubscribeToUIControls()
{
// Get Button components from children on this transform (NOTE: child names MUST be the same as what you are showing in Unity Editor)...
_playBtn = transform.Find("btn_play").GetComponent<Button>();
_pauseBtn = transform.Find("btn_pause").GetComponent<Button>();
_prevBtn = transform.Find("btn_prev").GetComponent<Button>();
_nextBtn = transform.Find("btn_next").GetComponent<Button>();
// Add OnClick Listeners...
_playBtn.onClick.AddListener(OnPlay);
_pauseBtn.onClick.AddListener(OnPause);
_prevBtn.onClick.AddListener(OnPrev);
_nextBtn.onClick.AddListener(OnNext);
}
/// <summary>
/// On play button pressed.
/// </summary>
private void OnPlay()
{
// Reset sequence back to start...
if (CurrentIndex == SequenceItems.Count-1)
{
ResetSequence();
}
// Flip play/pause button visibility...
_playBtn.gameObject.SetActive(false);
_pauseBtn.gameObject.SetActive(true);
// When Play button press, repeat call the OnNext() method..
InvokeRepeating("OnNext", sequenceIntervalDelay, sequenceIntervalDelay);
Debug.Log("Sequence Item " + CurrentIndex);
}
/// <summary>
/// On pause button pressed.
/// </summary>
private void OnPause()
{
// Stop the repeated call to OnNext()...
CancelInvoke("OnNext");
// Flip play/pause button visibility...
_playBtn.gameObject.SetActive(true);
_pauseBtn.gameObject.SetActive(false);
}
/// <summary>
/// On Prev Button Pressed.
/// </summary>
private void OnPrev()
{
if (CurrentIndex > 0)
{
// Hide the Sequence Item current index and decrement the index...
SequenceItems[_currentIndex].SetActive(false);
CurrentIndex--;
}
}
/// <summary>
/// On next Button pressed.
/// </summary>
private void OnNext()
{
if (CurrentIndex < SequenceItems.Count -1)
{
// If we are not at the end of the Sequence, increment the current index and make the Sequence Item at the new current index visible...
CurrentIndex++;
SequenceItems[CurrentIndex].SetActive(true);
}
else
{
// If we are at the end of the sequence, then stop the repeat call to the OnNext() method and swith play/pause button visibility...
CancelInvoke("OnNext");
_playBtn.gameObject.SetActive(true);
_pauseBtn.gameObject.SetActive(false);
}
}
/// <summary>
/// Resests the sequence back to the beginning.
/// </summary>
private void ResetSequence()
{
foreach (var go in SequenceItems)
{
go.SetActive(false);
}
SequenceItems.First().SetActive(true);
CurrentIndex = 0;
}
}
And here is the inspector of the Sequence Controller on the UI_SqncCtrls Game Object…

You can see the Public Properties for the List of Sequence Items and the Sequence Interval Delay in the inspector. By default the Sequence Items are an empty list, but you can populate this by dragging the Game Objects from your Scene Hierarchy onto the Sequence Items list in the inspector.
NOTE: the order they are in when dragging is the order they’ll be in the list, you should make sure they are in the right order in the Scene Hierarchy beforehand.
Now, I will elaborate on a couple of things, one of which is the InvokeRepeating() Method. This is a cool little function that repeatedly calls another function every x seconds. You can read more about it here in the docs, but it is dead simple to use and saves writing a coroutine. This is what I am using to iterate through the list of Sequence Items when the Play Button is pressed by passing in the same command I am using for the Next button.
InvokeRepeating("OnNext", sequenceIntervalDelay, sequenceIntervalDelay);
To stop the function being repeated, we can use the CancelInvoke() Method passing in the function name we want to stop being called. Again, you can read more about this here in the docs. In my case, I’m calling this when the Pause Button is pressed, or the Sequence has reached the end.
CancelInvoke("OnNext");
And that’s it! Well, that was pretty simple right?! Have a go building it yourself and adding more features!
As always, I hope you find this post useful and thanks for reading! š
Leave a Reply