A Simple AFK Timer

One of the best pieces of advice I was given for my first AVCon was to add an AFK Timer to my game. That meant if I was caught in conversation or distracted and a new user sat down at my kiosk they were going to have a fresh experience from the start. Not only that but it saves you constantly micro-managing the state of your game. As I was still learning how to create and release a full game last year I found that my timer was very title coupled to my code and not overly useful. Today I wrote a much more generic class that I am showing off in case anyone else finds it useful in the future. Here is a look at the code.

using System.Collections;
using UnityEngine;

public abstract class DemoInacTimer : MonoBehaviour {

    [SerializeField]
    [Range(0, 60.0f)]
    protected float afkTime = 30.0f; //How long to wait until we reset?
    [SerializeField]
    protected bool inDemoMode; //Toggle this on and off so you can leave it in your build if you want

    protected float elapsedTime = 0;
    protected Coroutine afkRoutine;

    //Start the timer when the object activates
    protected virtual void OnEnable() {
        if (inDemoMode) {
            afkRoutine = StartCoroutine(TimerRoutine()); 
        }
    }

    //Disable the coroutine if we deactivate the object
    protected virtual void OnDisable() {
        if (inDemoMode) {
            StopCoroutine(afkRoutine); 
        }
    }

    //Check for input to reset our timer
    protected virtual void Update() {
        if (inDemoMode) {
            CheckForInput();
        }
    }

    //Keeps the timer running while the object is alive. This means manually re-setting the elapsedTime
    //in either CheckForInput or ResetGame (or both) if this object is not destroyed when the game is reloaded.
    protected virtual IEnumerator TimerRoutine() {
        while (true) {
            if(elapsedTime >= afkTime) {
                ResetGame();
            } else {
                elapsedTime += Time.unscaledDeltaTime;
            }
            yield return new WaitForEndOfFrame();
        }
    }

    //Implement these two methods based on your games logic
    protected abstract void CheckForInput();
    protected abstract void ResetGame();
}

As you can see this is a very simple base class designed to be extended to suit the logic of your game. I’ve made this with the intention for one of your manager classes (if you have any) to extend it. This is useful because it means you can also add other logic in your manager related to whether the game is in demo mode, such as unlocking all cosmetics or removing in-game ads. To use this script you can do the following:

  1. Extend the DemoInacTimer class similar to the below:
    public class GameManager : DemoInacTimer {
  2. Implement the abstract methods of
    CheckForInput()

    and

    ResetGame()
  3. Test it!

Extending the DemoInacTimer class shows two fields in the editor as seen below.

afk_timer_editor

The range slider accepts float values from 0 – 60 but you can alter the time to suit if you want it to be longer.

CheckForInput() and ResetGame() are both abstract because I do not know how you want to implement checking for input in any of your games. As my game is on a mobile device I really only need to know if someone touches the screen. In Unity by default the touch of a single finger can also be checked with the MouseButtonDown(0) command. As a result I may implement my CheckForInput() method something like this.

protected override void CheckForInput() {
    if (Input.GetMouseButtonDown(0)) {
        elapsedTime = 0;
    }
}

Resetting the game could also be simple or extremely complex depending on the state of your game at any given time. I set mine up to be very simple so I can easily implement ResetGame().

protected override void ResetGame() {
    SceneManager.LoadScene(0);
}

You will also notice that the other classes are virtual and thus able to be overridden if need be. I assume that in many cases you will have more complex Update() or OnEnable() methods and thus you will need to call this base class before adding your own logic in. The timer is also able to be changed, in my case I added some logic to only increase the elapsedTime variable when the main menu was not shown as it seemed pointless to me to reset a game that was already on the front page.

I hope this helps if anyone has any further questions shoot me a tweet @thescottcabs.