I'm having trouble with invoke restart

When the player dies the game is to restart in 5 seconds.

But it keeps on restarting 5 seconds after the game starts. I had the restart code in a separate script but integrated it into the Player Death script just to make it easier.

The 1st place I put the invoke code was after every if-statement and the game didnt restart at all.
then tried it at the end of the OnTriggerEnter and that is when the game restarts after 5 seconds.

the code:


    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;

    public class PlayerDeath : MonoBehaviour
    {

    public GameObject objectToDestroy;
    public GameObject playerExplosionEffect;
    public float restartDelay = 5f;
    private AudioSource audioSource;

    void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Enemy")
        {
            Instantiate(playerExplosionEffect, transform.position, transform.rotation);
            Destroy(gameObject);
            vibratePhone();
           Invoke("Restart", restartDelay);  //NB: first place for invoke
            Debug.Log("Player touches enemy: Player Death script");
        }

        if (other.tag == "Obsidian")
        {
            Instantiate(playerExplosionEffect, transform.position, transform.rotation);
            Destroy(gameObject);
            vibratePhone();
           Invoke("Restart", restartDelay);  //NB: first place for invoke
            Debug.Log("Player touches Obsidian: Player Death script");
         }

        if (other.tag == "EnemyBolt")
        {
            Instantiate(playerExplosionEffect, transform.position, transform.rotation);
            Destroy(gameObject);
            vibratePhone();
           Invoke("Restart", restartDelay);  //NB: first place for invoke
            Debug.Log("Player hit: Player Death script");
        }

        Invoke("Restart", restartDelay); //NB: second place for invoke
        //FindObjectOfType<NewGameManager>().EndGame(); //NB: This was to direct the code to the original restart script
    }

    public void vibratePhone()
    {
       Handheld.Vibrate();
       Debug.Log("Vibration: Player Death script");
    }

    public void Restart()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        Debug.Log("Game Over: Game Manager script");
    }
    }

Does anyone have any suggestions?

Please use code tags , as per the forum guidelines.

1 Like

Inside of the conditionals, you’re invoking a function on a GameObject after destroying said GameObject. This isn’t going to work. Even if Restart wasn’t a function attached to the current GameObject, the Invoke call is, and so I’d expect the invoke to never actually finish because its “owner” is destroyed in the scene.

If you’d like to make the player “vanish” immediate, you could turn off the renderer instead. My advice though is to remove the Invoke on line 44 completely, then put Restart in some sort of manager object instead of on the player. If you wish, you can still destroy the GameObject here, but make sure it’s at the end of the conditional clause it’s in. Destroying the current MonoBehaviour instance / GameObject it resides on should be your final act within that object- don’t expect additional methods to be able to be run on them afterward. I’d also use “else if” instead of a bunch of “if” clauses back to back, so that it’s not continuing to check them if one of the “ifs” is true and the object is destroyed halfway through the method.

If you want to be dead-simple about the manager, just make a public/serialized reference in this class pointing to it, and fire Restart from that instead. The manager object should be higher in the scene hierarchy so that it’s not destroyed by this Destroy(gameObject) call.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerDeath : MonoBehaviour
{
    [SerializeField] private PlayerManager playerManager;
    [SerializeField] private GameObject playerExplosionEffect;
    [SerializeField] private AudioSource audioSource;


    private void OnTriggerEnter(Collider other)
    {
        Debug.Log("Player entered trigger area...");

        if (other.tag == "Enemy")
        {
            Instantiate(playerExplosionEffect, transform.position, transform.rotation);
            playerManager.VibratePhone();
            playerManager.Restart();
            Debug.Log("Player touches enemy: Player Death script");
            Destroy(gameObject);
        }
        else if (other.tag == "Obsidian")
        {
            Instantiate(playerExplosionEffect, transform.position, transform.rotation);
            playerManager.VibratePhone();
            playerManager.Restart();
            Debug.Log("Player touches Obsidian: Player Death script");
            Destroy(gameObject);
        }
        else if (other.tag == "EnemyBolt")
        {
            Instantiate(playerExplosionEffect, transform.position, transform.rotation);
            playerManager.VibratePhone();
            playerManager.Restart();
            Debug.Log("Player hit: Player Death script");
            Destroy(gameObject);
        }
    }
}

Things that don’t “belong” to the player, like vibrating the phone and restarting the scene, shouldn’t really be managed by the Player object.

Thanks for that