Unity3D How To Create A Simple Countdown Timer

Unity3D How To Create A Simple Countdown Timer

I needed a simple countdown timer to create a splash screen effect so I could jump to the next scene. In this example, I create a time governor that loops and keeps checking to see if the time has expired ( <= 0 ) then executes the actions.

Set Total Countdown Time

In your class create a float variable that will be the total amount of time to countdown and the reset time holder:
public class CountDownTimer : Monobehaviour {

float timeRemaining; // the timer
float timeRemainingReset; // the timer reset

Add To A Main Update Loop

Add this code to any of your main update loops (Update, FixedUpdate, LateUpdate):
void Update() {
     timeRemaining -= Time.deltaTime; // subtract time each frame

     if( timeRemaining <= 0 ) {
          // reset the timer
          timeRemaining = timeRemainingReset;
          // perform your actions (load next scene, move a gameobject, perform garbage clean up etc.)
          HealPlayer();
          CheckCombat();
     }
}

Unity3D How To Create A Simple Countdown Timer

Yet Another State Machine

Unity3D Yet Another State Machine

If logic in your controller to complex for ‘if’ or ‘switch\case’ constructions, here is small State Machine implementation for you.

Let’s start with example how to use this state machine, and then we go through implementation details:
public class Test : MonoBehaviour
{
    private StateMachine stateMachine;
 
    private State firstState = new State();
    private State secondState = new CustomState();
    private State finishState = new State();
 
    // Use this for initialization
    void Start ()
    {
        var initChild = new State()
            .AddStartAction(() => Debug.Log(Time.frameCount + " childInit Start"))
            .AddUpdateAction(() => Debug.Log(Time.frameCount + " childInit Update"))
            .AddStopAction(() => Debug.Log(Time.frameCount + " childInit Stop"));
        var childStateMachine = new StateMachine(initChild);
        stateMachine = new StateMachine(firstState);
 
        firstState
            .AddStartAction(() => Debug.Log(Time.frameCount + " 1 Start"))
            .AddUpdateAction(() => Debug.Log(Time.frameCount + " 1 Update"))
            .AddStopAction(() => Debug.Log(Time.frameCount + " 1 Stop"))
            .AddTransition(
                state => Time.frameCount == 5, 
                secondState)
            .AddTransition(
                state => Time.frameCount == 15,
                secondState);
 
        secondState
            .AddTransition(
                state => Time.frameCount == 10,
                firstState)
            .AddTransition(
                state => Input.GetKey(KeyCode.Q),
                childStateMachine);
 
        childStateMachine
            .AddTransition(s => Input.GetKey(KeyCode.Y), finishState);
 
        finishState
            .AddStartAction(() => Debug.Log(Time.frameCount + " finish Start"));
 
        stateMachine.Start();
    }
 
    void Update()
    {
        stateMachine.Update();
    }
}
 
public class CustomState : State
{
    public CustomState()
    {
        StartAction = CustomStart;
        UpdateAction = CustomUpdate;
        StopAction = CustomStop;
    }
 
    public void CustomStart()
    {
        Debug.Log(Time.frameCount + " custom start");
    }
 
    public void CustomUpdate()
    {
        Debug.Log(Time.frameCount + " custom update");
    }
 
    public void CustomStop()
    {
        Debug.Log(Time.frameCount + " custom stop");
    }
}

Each state might have couple Start, Update and Stop actions. You can add them through AddStartAction\AddUpdateAction\AddStopAction methods. Those actions are not required, so state could have only Start and Update, but not Stop action, or could be even without any actions.

Also, each state might have transitions. To add them use AddTransition method. It takes predicate and next state as arguments.

If state machine is in a some state it will check all registered transitions of the current state. If any of conditions return true, it will go to next state and will call all actions Stop for current state and Start for next state.

If current state has transitions, but all conditions return false, state machine just call Update action of the current state and will check transitions again only in the next frame.

Here is State and StateMachine implementation:
public class State
{
    private readonly List transitions = new List();
 
    protected Action StartAction { get; set; }
    protected Action StopAction { get; set; }
    protected Action UpdateAction { get; set; }
 
    protected internal bool IsStarted { get; set; }
 
    protected internal void Start()
    {
        if (!IsStarted && StartAction != null)
        {
            StartAction();
            IsStarted = true;
        }
    }
 
    protected internal void Update()
    {
        if (IsStarted && UpdateAction != null)
        {
            UpdateAction();
        }
    }
 
    protected internal void Stop()
    {
        if (IsStarted && StopAction != null)
        {
            StopAction();
            IsStarted = false;
        }
    }
 
    public State AddStartAction(Action startAction)
    {
        StartAction += startAction;
        return this;
    }
 
    public State AddUpdateAction(Action updateAction)
    {
        UpdateAction += updateAction;
        return this;
    }
 
    public State AddStopAction(Action stopAction)
    {
        StopAction += stopAction;
        return this;
    }
 
    public State AddTransition(Predicate condition, State nextState)
    {
        transitions.Add(new StateTransition(condition, nextState));
        return this;
    }
 
    public bool CanGoToNextState(out State nextState)
    {
        for (int i = 0; i < transitions.Count; i++)
        {
            if (transitions[i].Condition(this))
            {
                nextState = transitions[i].NextState;
                return true;
            }
        }
 
        nextState = null;
        return false;
    }
 
    public bool HasNextState()
    {
        return transitions.Count != 0;
    }
}
StateMachine:
public class StateMachine : State
{
    private readonly State initialState;
    public State CurrenState { get; private set; }
 
    public StateMachine(State initialState)
    {
        this.initialState = initialState;
        StartAction = Start;
        UpdateAction = Update;
        StopAction = Stop;
    }
 
    public new void Start()
    {
        if (IsStarted)
        {
            return;
        }
 
        CurrenState = initialState;
        CurrenState.Start();
        IsStarted = true;
    }
 
    public new void Update()
    {
        if (CurrenState == null)
        {
            return;
        }
 
        if (!CurrenState.IsStarted)
        {
            CurrenState.Start();
        }
 
        CurrenState.Update();
 
        State nextState;
        while (CurrenState.CanGoToNextState(out nextState))
        {
            if (CurrenState.IsStarted)
            {
                CurrenState.Stop();
            }
 
            CurrenState = nextState;
 
            if (!CurrenState.IsStarted)
            {
                CurrenState.Start();
            }
 
            CurrenState.Update();
        }
 
        if (!CurrenState.HasNextState())
        {
            Stop();
        }
    }
 
    public new void Stop()
    {
        if (CurrenState == null)
        {
            return;
        }
 
        if (CurrenState.IsStarted)
        {
            CurrenState.Stop();
        }
 
        CurrenState = null;
    }
}
As you can see, you can easily extend State by inherit from State class and specifying Start\Stop\Update actions. You can also use StateMachine as a State, so you can create hierarchical structure.

Unity3D Yet Another State Machine

How-To Play Video in Unity Project Using MovieTexture

Unity3D How-To Play Video in Unity Project Using MovieTexture

If you want to play movie clip in your Unity3d project you need to have Pro version!

If you are using Windows machine you also need to have QuickTime installed.

After you have everything prepared just drag (or copy) your movie clip into Asset folder, after that you will see it imported.

You need a MovieTexture instance to use imported clip. To play movie clip use following code:
MovieTexture movie;
public void Play()
{
    movie.Play();
}

To stop or pause:
movie.Pause();
movie.Stop();

You can access audio clip through audioClip field:

var audio = movie.audioClip;
Importing problems

First, check if you have Apple Quick Time installed.

If you working with a team, it might be a problem when someone imported videos in the project, but you still see them as a simple files. To fix that just select movies and reimport them. For some reason, Unity doesn’t do that automatically.

Unity3D How-To Play Video in Unity Project Using MovieTexture

Unity ReadOnly InputField

Unity3D ReadOnly InputField

New UI system was introduced in Unity3d 4.6, it includes InputField control, but this field could not be read only. You can make it non interactable by disabling “Interactable” property in the editor, but then you will not be able to select and copy text from InputField.

To have proper ReadOnly input field you should do small modification to the original control:
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
 
[AddComponentMenu("UI/Read Only Input Field", 32)]
public class ReadOnlyInputField : InputField
{
    private Event m_ProcessingEvent = new Event();
 
    public override void OnUpdateSelected(BaseEventData eventData)
    {
        if (!isFocused)
            return;
 
        bool consumedEvent = false;
        while (Event.PopEvent(m_ProcessingEvent))
        {
            if (m_ProcessingEvent.rawType == EventType.KeyDown)
            {
                if (!IsAllowedCombination(m_ProcessingEvent))
                {
                    continue;
                }
 
                consumedEvent = true;
 
                var shouldContinue = KeyPressed(m_ProcessingEvent);
                if (shouldContinue == EditState.Finish)
                {
                    DeactivateInputField();
                    break;
                }
            }
        }
 
        if (consumedEvent)
        {
            UpdateLabel();
        }
 
        eventData.Use();
    }
 
    private bool IsAllowedCombination(Event evt)
    {
        var currentEventModifiers = evt.modifiers;
        RuntimePlatform rp = Application.platform;
        bool isMac = (rp == RuntimePlatform.OSXEditor || rp == RuntimePlatform.OSXPlayer || rp == RuntimePlatform.OSXWebPlayer);
        bool ctrl = isMac ? (currentEventModifiers & EventModifiers.Command) != 0 : (currentEventModifiers & EventModifiers.Control) != 0;
 
        switch (evt.keyCode)
        {
            case KeyCode.Home:
            case KeyCode.End:
            case KeyCode.LeftControl:
            case KeyCode.RightControl:
            {
                return true;
            }
 
            // Select All
            case KeyCode.A:
            {
                if (ctrl)
                {
                    return true;
                }
                break;
            }
 
            // Copy
            case KeyCode.C:
            {
                if (ctrl)
                {
                    return true;
                }
                break;
            }
 
            case KeyCode.LeftArrow:
            case KeyCode.RightArrow:
            case KeyCode.UpArrow:
            case KeyCode.DownArrow:
            {
                return true;
            }
        }
 
        return false;
    }
}

Now you can add this component to your control or replace InputField component with this one on existing game object.

Unity3D ReadOnly InputField

Unity WaitForFrames in Coroutine

Unity3D WaitForFrames in Coroutine

If you are using Coroutines in Unity3d, you probably know about WaitForSeconds, WaitForEndOfFrame and WaitForFixedUpdate classes. Here is an example:
public IEnumerator CoroutineAction()
{
    // do some actions here    
    yield return new WaitForSeconds(2); // wait for 2 seconds
    // do some actions after 2 seconds
}

But sometimes you need to wait for some amount of frames before executing some action. I have created simple class to help you with that:
public static class WaitFor
{
    public static IEnumerator Frames(int frameCount)
    {
        if (frameCount <= 0)
        {
            throw new ArgumentOutOfRangeException("frameCount", "Cannot wait for less that 1 frame");
        }
 
        while (frameCount > 0)
        {
            frameCount--;
            yield return null;
        }
    }
}

Now you can wait for frames:
public IEnumerator CoroutineAction()
{
    // do some actions here    
    yield return StartCoroutine(WaitFor.Frames(5)); // wait for 5 frames
    // do some actions after 5 frames
}

Unity3D WaitForFrames in Coroutine

Unity Horizontal Field Of View for Camera

Unity3D Horizontal Field Of View for Camera

In Unity3d you can change only vertical field of view for a camera by default. This means whenever you change height unity will automatically scale environment. But if you change width unity will just add some space (or decrease) to left and right side of the screen (no content resizing).

If you want to have opposite behavior, so when you increase width all content will be scaled and if you increase height only space added to the view, you need to modify camera fieldOfView field.

Here is a simple component that do this:
public class HorizontalFOV : MonoBehaviour {
public float fieldOfView = 60;
  
void Update () {
    camera.fieldOfView = fieldOfView / ((float)camera.pixelWidth / camera.pixelHeight);
    }
}

You can also modify it a bit to have the same view for default aspect ration:
public class HorizontalFOV : MonoBehaviour {
public float fieldOfView = 60;
  
void Update () {
    camera.fieldOfView = fieldOfView * (16f/9f) / ((float)camera.pixelWidth / camera.pixelHeight);
    }
}

Unity3D Horizontal Field Of View for Camera

Unity3D Camera Shake Script

Unity3D Camera Shake Free Script

After much Googling for how to do a camera shaking effect in Unity, I decided to write my own small script to accomplish the effect. It combines both positional movement with rotational movement to simulate closely an actual camera shake.
The two key variables are:

shake_intensity

Shake_intensity determines the initial intensity of the shaking — how much variance to allow in the camera position.

shake_decay

Shake_decay controls is the amount that shake_intensity is decremented each update. It determines if the shake is long or short.

JavaScript
var originPosition:Vector3;
var originRotation:Quaternion;
var shake_decay: float;
var shake_intensity: float;;
 
function OnGUI () {
   if (GUI.Button (Rect (20,40,80,20), "Shake")) {
      Shake();
   }
}
 
function Update(){
   if(shake_intensity > 0){
      transform.position = originPosition + Random.insideUnitSphere * shake_intensity;
      transform.rotation = Quaternion(
      originRotation.x + Random.Range(-shake_intensity,shake_intensity)*.2,
      originRotation.y + Random.Range(-shake_intensity,shake_intensity)*.2,
      originRotation.z + Random.Range(-shake_intensity,shake_intensity)*.2,
      originRotation.w + Random.Range(-shake_intensity,shake_intensity)*.2);
      shake_intensity -= shake_decay;
   }
}
 
function Shake(){
   originPosition = transform.position;
   originRotation = transform.rotation;
   shake_intensity = .3;
   shake_decay = 0.002;
}

C#
using UnityEngine;
using System.Collections;
public class cameraShake : MonoBehaviour
{
   private Vector3 originPosition;
   private Quaternion originRotation;
   public float shake_decay;
   public float shake_intensity;
 
   void OnGUI (){
      if (GUI.Button (new Rect (20,40,80,20), "Shake")){
         Shake ();
      }
   }
 
   void Update (){
      if (shake_intensity > 0){
         transform.position = originPosition + Random.insideUnitSphere * shake_intenity;
         transform.rotation = new Quaternion(
         originRotation.x + Random.Range (-shake_intensity,shake_intensity) * .2f,
         originRotation.y + Random.Range (-shake_intensity,shake_intensity) * .2f,
         originRotation.z + Random.Range (-shake_intensity,shake_intensity) * .2f,
         originRotation.w + Random.Range (-shake_intensity,shake_intensity) * .2f);
         shake_intensity -= shake_decay;
      }
   }
 
   void Shake(){
      originPosition = transform.position;
      originRotation = transform.rotation;
      shake_intensity = .3f;
   shake_decay = 0.002f;
   }
}

Unity3D Camera Shake Free Script