WACK-A-MOLE QUEST: ‘Restart The Action’ - Solutions

Quest: Wack-A-Mole
Challenge: Restart The Action

Feel free to share your solutions, ideas and creations below. If you get stuck, you can find some ideas here for completing this challenge.

So the majority of this challenge was working with scripts (see below) but I did rename “TheEnemy” prefab to “Enemy” and move it into the Resources folder. I also added a material to the prefab so that my new enemies would be born looking like something other than the dreaded ‘Default Cube’ :slight_smile:

Timer.cs

using UnityEngine;
using UnityEngine.UI;

public class Timer : MonoBehaviour
{
    Text timerText;
    float elapsedTime;
    float totalTime;
    bool gameIsActive = false;

    public void ToggleActive() { gameIsActive = !gameIsActive; }
    public bool GetIsActive() { return gameIsActive; }

    public void ClearTime()
    {
        UpdateTotalTime();
        elapsedTime = 0f;
    }

    void Start()
    {
        timerText = GetComponent<Text>();
    }

    void Update()
    {
        if(gameIsActive) elapsedTime += Time.deltaTime;
        if(!gameIsActive) timerText.text = Mathf.RoundToInt(totalTime).ToString();
        else timerText.text = Mathf.RoundToInt(elapsedTime).ToString();
    }

    void UpdateTotalTime()
    {
        totalTime += elapsedTime;
    }
}

Scorer.cs

using UnityEngine;

public class Scorer : MonoBehaviour
{
    [SerializeField] ParticleSystem celebration;

    bool hasPlayed = false;
    int gameCount = 0;

    Timer timer;

    private void Start()
    {
        timer = FindObjectOfType<Timer>();
    }

    void Update()
    {
        if (transform.childCount == 0 && !hasPlayed)
        {
            timer.ToggleActive();
            PlayWinParticles();
            gameCount++;
            Invoke("Restart", 5f);
        }
    }

    private void PlayWinParticles()
    {
        if (!hasPlayed)
        {
            celebration.Play();
            hasPlayed = true;
        }
        else celebration.Stop();
    }

    void Restart()
    {
        for (int i = 1; i < Mathf.RoundToInt(Random.Range(0, 10)); i++)
        {
            GameObject gObject = Instantiate(Resources.Load("Enemy"), new Vector3(0f,-1.25f,0f), Quaternion.identity) as GameObject;
            gObject.name = "Enemy" + i;
            gObject.transform.parent = this.transform;
        }
        timer.ClearTime();
        foreach(var mover in GetComponentsInChildren<EnemyMover>()) mover.StartRound();
        hasPlayed = false;
    }
}

Timer.cs

public class Timer : MonoBehaviour
{
    Text timerText;
    float elapsedTime;
    WaitForSecondsRealtime WaitForSecondsRealtime;
    float secondsToWait = 0.2f;

    void Start()
    {
        WaitForSecondsRealtime = new WaitForSecondsRealtime(secondsToWait);
        timerText = GetComponent<Text>();
    }

    private void Update()
    {
        elapsedTime += Time.deltaTime;
        timerText.text = Mathf.RoundToInt(elapsedTime).ToString();
    }

    public IEnumerator ResetTimer()
    {
        yield return WaitForSecondsRealtime;
        elapsedTime = 0;
        timerText.text = elapsedTime.ToString();
    }
}

Scorer.cs

public class Scorer : MonoBehaviour
{
    [SerializeField] private float startTimer;
    [SerializeField] private float timerWaitFor = 2f;

    [SerializeField] ParticleSystem celebration;
    [SerializeField] SpawnCubesAtRandom spawner;
    [SerializeField] Timer timer;
    bool hasChildren = true;

    void Update()
    {
        if (spawner.enemies.Count <= 0)
        {
            celebration.Play();
            startTimer += Time.deltaTime;
            hasChildren = false;
        }

        if (!hasChildren && startTimer >= timerWaitFor)
        {
            celebration.Stop(false, ParticleSystemStopBehavior.StopEmittingAndClear);
            startTimer = timerWaitFor;
            StartCoroutine(timer.ResetTimer());
            SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
        }
    }
}
1 Like

Timer.cs

public class Timer : MonoBehaviour
{
    Text timerText;
    float elapsedTime;

    void Start()
    {
        timerText = GetComponent<Text>();
    }

    void Update()
    {
        elapsedTime = Time.timeSinceLevelLoad;
        timerText.text = elapsedTime.ToString("0");
    }

    public void TimerReset()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }
}

Scorer.cs

public class Scorer : MonoBehaviour
{
    [SerializeField] ParticleSystem celebration;

    private Timer timer;
    private bool hasChildren = true;
    private float delay = 2f;

    private const string TIMER_RESET = "TimerReset";

    private void Start()
    {
        timer = GameObject.FindObjectOfType<Timer>();    
    }

    void Update()
    {
        if (transform.childCount == 0 && hasChildren)
        {
            celebration.Play();
            hasChildren = !hasChildren;
            timer.Invoke(TIMER_RESET, delay);
        }
    }
}

Initially, I created a ResetTimer method in Timer.cs and used a FindObjectOfType in Scorer.cs to find/call the method. A simpler solution was to return to the previous challenge where elapsedTime was set to follow “Time.time”, and replace this with “Time.timeSinceLevelLoad”. This way, elapsedTime resets automatically when the level is reloaded.

All that was needed then was a simple Coroutine in Scorer.cs.

    IEnumerator ResetGame()
    {
        yield return new WaitForSeconds(2);
        SceneManager.LoadScene(0);
    }

Privacy & Terms