Gameover scene doesn't work

my gameover scene doesn’t load I know the reason is cuz my gameobject gets destroyed where script is attached to but I don’t know how to fix it. I tried a lot so code might look weird.
Player script

using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.XR.WSA.Input;
using UnityEngine.SceneManagement;

public class Player : MonoBehaviour
{
    
    //config param
    [Header("Player")]
    [SerializeField] float MoveSpeed = 10f;
    [SerializeField] float padding = 1f;
    [SerializeField] int health = 200;


    DamageDealer damageDealer;
    Level level;
    [SerializeField] int delayInSeconds = 2;

    [SerializeField] AudioClip playerShot;
    [SerializeField] AudioClip playerDeath;
    [SerializeField] [Range(0, 1)] float deathVolume = 0.7f;
    [SerializeField] [Range(0, 1)] float laserVolume = .4f;

    [Header("Projectile")]

    [SerializeField] GameObject laserPrefab;
    [SerializeField] float projectileSpeed = 10f;
    [SerializeField] float projectileFiringPeriod = 0.2f;
    Coroutine firingCoroutine;


    float xMin;
    float xMax;

    float yMin;
    float yMax;
    // Start is called before the first frame update
    void Start()
    {
        SetUpMoveBoundries();
        
    }

    

    // Update is called once per frame
    void Update()
    {
        Move();
        Fire();
    }
    private void OnTriggerEnter2D(Collider2D collision)
    {
        health -= 100;
        if (health <= 0)
        {
            FindObjectOfType<Level>().LoadGameOver();
            Destroy(gameObject);
            AudioSource.PlayClipAtPoint(playerDeath, Camera.main.transform.position, deathVolume);
            
        }
        if (!damageDealer) { return; }
        damageDealer.Hit();
    }
    private void Fire()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            firingCoroutine = StartCoroutine(FireContinuously());
        }
        if (Input.GetButtonUp("Fire1"))
        {
            StopCoroutine(firingCoroutine);
        }
    }
    IEnumerator FireContinuously()
    {
        while (true)
        {
            GameObject laser = Instantiate(laserPrefab, transform.position, Quaternion.identity) as GameObject;
            AudioSource.PlayClipAtPoint(playerShot, Camera.main.transform.position, laserVolume);
            laser.GetComponent<Rigidbody2D>().velocity = new Vector2(0, projectileSpeed);
            yield return new WaitForSeconds(projectileFiringPeriod);
            
        }
    }

    private void Move()
    {
        var deltaX = Input.GetAxis("Horizontal")* Time.deltaTime;
        var deltaY = Input.GetAxis("Vertical") * Time.deltaTime;

        var newxPos = Mathf.Clamp(transform.position.x + deltaX * MoveSpeed, xMin, xMax);

        var newyPos = Mathf.Clamp(transform.position.y + deltaY * MoveSpeed, yMin, yMax);

        transform.position = new Vector2(newxPos,newyPos );
       
    }
    private void SetUpMoveBoundries()
    {
        Camera gameCamera = Camera.main;
        xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).x + padding;
        xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, 0)).x - padding;

        yMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).y + padding;
        yMax = gameCamera.ViewportToWorldPoint(new Vector3(0, 1, 0)).y - padding;
    }
    IEnumerator WaitAndLoad()
    {
        yield return new WaitForSeconds(delayInSeconds);
        SceneManager.LoadScene("GameOver Scene");
    }

}

Level Script

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

public class Level : MonoBehaviour
{
    [SerializeField] int delayInSeconds = 2;
  public void LoadStartMenu()
    {
        SceneManager.LoadScene("Start Scene");
    }
    public void LoadGameOver()
    {
        SceneManager.LoadScene("GameOver Scene");

    }
    public void LoadGameScene()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    }
    public void QuitGame()
    {
        Application.Quit();
    }
   
}

Hi Prajaney,

You already identified the problem correctly. Is there a reason why WaitAndLoad gets called inside the Player instance instead of the Level instance?

no, I was messing around with coroutines to figure out the problem, so I introduced it but forgot to remove it.

it seems like gameover scene doesn’t load only when I collide with enemy, even though the player gameobject gets destroyed.

The coroutine gets stopped immediately when the object in which you start it gets destroyed. If the player gets destroyed and you start a coroutine inside the Player instance, the coroutine gets terminated along with the Player instance.

Ya, so what do I do? And how come it works fine when I die with laser or when I frist get hit by laser and then collide with enemy then also it works fine. It only messes when I collide with enemy straight.

Remove the WaitAndLoad coroutine from the Player and move it to Level. In Player, you can call the LoadGameOver of the Level instance and have the LoadGameOver method start your WaitAndLoad coroutine.

I tried that it still doesn’t work. It only happens if I die with enemy only. Any other way I die it works.

What are the alternative ways for the player to die? And could you share the code based on my description of a potential solution and which doesn’t work?

Player

using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.XR.WSA.Input;
using UnityEngine.SceneManagement;
using UnityEditor.Android;

public class Player : MonoBehaviour
{

    //config param
    [Header("Player")]
    [SerializeField] float MoveSpeed = 10f;
    [SerializeField] float padding = 1f;
    [SerializeField] int health = 200;


    DamageDealer damageDealer;
    Level level;


    [SerializeField] AudioClip playerShot;
    [SerializeField] AudioClip playerDeath;
    [SerializeField] [Range(0, 1)] float deathVolume = 0.7f;
    [SerializeField] [Range(0, 1)] float laserVolume = .4f;

    [Header("Projectile")]

    [SerializeField] GameObject laserPrefab;
    [SerializeField] float projectileSpeed = 10f;
    [SerializeField] float projectileFiringPeriod = 0.2f;
    Coroutine firingCoroutine;


    float xMin;
    float xMax;

    float yMin;
    float yMax;
    // Start is called before the first frame update
    void Start()
    {
        SetUpMoveBoundries();

    }



    // Update is called once per frame
    void Update()
    {
        Move();
        Fire();
    }
    private void OnTriggerEnter2D(Collider2D collision)
    {
        health -= 100;
        if (health <= 0)
        {
            FindObjectOfType<Level>().LoadGameOver();
            Destroy(gameObject);
            AudioSource.PlayClipAtPoint(playerDeath, Camera.main.transform.position, deathVolume);

        }
        if (!damageDealer) { return; }
        damageDealer.Hit();
    }
    private void Fire()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            firingCoroutine = StartCoroutine(FireContinuously());
        }
        if (Input.GetButtonUp("Fire1"))
        {
            StopCoroutine(firingCoroutine);
        }
    }
    IEnumerator FireContinuously()
    {
        while (true)
        {
            GameObject laser = Instantiate(laserPrefab, transform.position, Quaternion.identity) as GameObject;
            AudioSource.PlayClipAtPoint(playerShot, Camera.main.transform.position, laserVolume);
            laser.GetComponent<Rigidbody2D>().velocity = new Vector2(0, projectileSpeed);
            yield return new WaitForSeconds(projectileFiringPeriod);

        }
    }

    private void Move()
    {
        var deltaX = Input.GetAxis("Horizontal") * Time.deltaTime;
        var deltaY = Input.GetAxis("Vertical") * Time.deltaTime;

        var newxPos = Mathf.Clamp(transform.position.x + deltaX * MoveSpeed, xMin, xMax);

        var newyPos = Mathf.Clamp(transform.position.y + deltaY * MoveSpeed, yMin, yMax);

        transform.position = new Vector2(newxPos, newyPos);

    }
    private void SetUpMoveBoundries()
    {
        Camera gameCamera = Camera.main;
        xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).x + padding;
        xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, 0)).x - padding;

        yMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).y + padding;
        yMax = gameCamera.ViewportToWorldPoint(new Vector3(0, 1, 0)).y - padding;
    }

}

Level

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

public class Level : MonoBehaviour
{
    [SerializeField] int delayInSeconds = 2;
  public void LoadStartMenu()
    {
        SceneManager.LoadScene("Start Scene");
    }
    public void LoadGameOver()
    {
        StartCoroutine(WaitAndLoad());

    }
    public void LoadGameScene()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    }
    public void QuitGame()
    {
        Application.Quit();
    }
    IEnumerator WaitAndLoad()
    {
        
        yield return new WaitForSeconds(delayInSeconds);        
        SceneManager.LoadScene("GameOver Scene");
            
    }

}

with this code if I die with 2 lasers the coroutine works. if i die with 1 laser and crashing to an enemy it still works. only when i crash with an enemy and die the coroutine doesn’t work.

I found the solution if I changed

 private void OnTriggerEnter2D(Collider2D collision)
    {
        health -= 100;

to

private void OnTriggerEnter2D(Collider2D collision)
    {
        health -= FindObjectOfType<DamageDealer>().GetDamage();

everything worked fine. but why? and also thank you so much for helping me, an absolute idiot. And sorry for bothering you so much.

Good question. The first one should have worked as well because GetDamage returns an integer value, not anything special. Maybe the returned value is lower than 100, and the problem was based on a misunderstanding?

How are you getting on with this, @prajaney?


See also:

Privacy & Terms