Yet another approach to prevent double play and player input

My approach is setting Time.timeScale to 0 in the Trigger handler. This will pause the game so no input can be entered and no additional collisions can take place. Like so:

// <In CrashDetector>
    void OnCollisionEnter2D(Collision2D other) {
        if (other.gameObject.tag == "Obstacle") {
            Crash();
        }
    }

    private void Crash() {
        ....
        // Play the crash effect
        crashEffect.Play();
        StartCoroutine(PauseAfterEffect());

        // Reload the scene after a delay
        StartCoroutine(ReloadSceneAfterDelay());
    }

    IEnumerator PauseAfterEffect() {
        yield return new WaitForSeconds(Mathf.Max(crashEffect.main.duration, crashSound.clip.length));
        Time.timeScale = 0f;
    }
    IEnumerator ReloadSceneAfterDelay() {
        // Use unscaledTime since the scene is paused
        yield return new WaitForSecondsRealtime(reloadDelay);
        // Reset timeScale before loading new scene
        Time.timeScale = 1f;
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }

Some notes:

  1. I make sure to only pause once the crash effect and crash sound have finished, for better experience. Technically the player can still move during this short interval
  2. In order to reload the scene properly, we have to use WaitForSecondsRealtime once the scene is paused since WaitForSeconds uses “game time” and once we set timeScale = 0 game time does not advance. I think we also need to reset the time scale back to 1 in order for the scene to reload. I haven’t tested whether this approach would work with Invoke instead of a coroutine but I suspect it wouldn’t.

Privacy & Terms