Delay for Loading Scene within the Player Script?

Hi!
Regarding the Delay for Loading Scene section, I got Rick’s solution to work but was trying to understand why my method did not work.

What I (think) I did was try to run the exact same coroutine as Rick’s solution to have a Delay for loading scene, but in the “Player” script instead of the Level Script. Below is a portion of my Player script in question. FYI, at the very top of the script I added “using UnityEngine.SceneManagement;” and also Serialized “WaitTime”. It seemed to me structurally it was all the same as Rick’s code, but when I ran the game, the GameOver screen was not loaded even if I waited a long time. Is there something here that I’m not understanding about Coroutines? Why does Rick’s way work just by putting the Corouting in the “Player” script and getting that code from the Player script?

Thanks in advance!

private void Die()
{
    GameOver();
    Destroy(gameObject);
    AudioSource.PlayClipAtPoint(deathPlayerSound, Camera.main.transform.position, deathSoundVolume);
    GameObject explosion = Instantiate(explosionPlayer, transform.position, transform.rotation) as GameObject;
    Destroy(explosion, 0.25f);
}

public void GameOver()
{
    StartCoroutine(EndGame());
}

IEnumerator EndGame()
{
    yield return new WaitForSeconds(WaitTime);
    SceneManager.LoadScene("GameOver");
} 


private void Die()
{
    GameOver();
    Destroy(gameObject);
    AudioSource.PlayClipAtPoint(deathPlayerSound, Camera.main.transform.position, deathSoundVolume);
    GameObject explosion = Instantiate(explosionPlayer, transform.position, transform.rotation) as GameObject;
    Destroy(explosion, 0.25f);
}

public void GameOver()
{
    StartCoroutine(EndGame());
}

IEnumerator EndGame()
{
    yield return new WaitForSeconds(WaitTime);
    SceneManager.LoadScene("GameOver");
}

Hi,

Is this your solution or Rick’s? And why are the method there twice? Was it an accident? Or did you want to show a difference?

Sorry, I must have pasted it twice. Yes, this is my solution. I’m just saying the portion with the coroutine (to me) seems identical to Rick’s solution, except that his coroutine and Load Game Over code was located in the Level script (where all the Load scene methods are located) whereas my coroutine is just in the “Player” script.

I’m pasting the whole code of my Player script below just in case, the Load Game Over screen with delay coroutine is at the end:

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

public class Player : MonoBehaviour
{
    [Header("Player Movement")]
    [SerializeField] float moveSpeed = 10f;
    [SerializeField] float padding = 1f;
    [SerializeField] int health = 200;
    [SerializeField] GameObject explosionPlayer;
    [SerializeField] AudioClip deathPlayerSound;
    [SerializeField] AudioClip impactSound;
    [SerializeField] GameObject impactFX;
    [SerializeField] [Range(0,1)] float deathSoundVolume = 0.7f;
    [SerializeField] [Range(0, 1)] float laserSoundVolume = 0.7f;
    [SerializeField] [Range(0, 1)] float impactSoundVolume = 0.7f;
    [SerializeField] float WaitTime = 0.5f;


    [Header("Projectile")]
    [SerializeField] GameObject laserPrefab;
    [SerializeField] float projectileSpeed = 10f;
    [SerializeField] float projectileFiringPeriod = 0.1f;
    [SerializeField] AudioClip playerLaserSFX;

    Coroutine firingCoroutine;

    float xMin;
    float xMax;
    float yMin;
    float yMax;

    // Start is called before the first frame update
    void Start()
    {
        SetUpMoveBoundaries();
    }

    // Update is called once per frame
    void Update()
    {
        Move();
        Fire();
    }

    private void Fire()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            firingCoroutine = StartCoroutine(FireContinuously());
        }
        if (Input.GetButtonUp("Fire1"))
        {
            StopCoroutine(firingCoroutine);
        }
    }

    private void Move()
    {
        var deltaX = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
        var newXPos = Mathf.Clamp(transform.position.x + deltaX, xMin, xMax);
        var deltaY = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeed;
        var newYPos = Mathf.Clamp(transform.position.y + deltaY, yMin, yMax);
        transform.position = new Vector2(newXPos, newYPos);
    }

    private void SetUpMoveBoundaries()
    {
        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 FireContinuously()
    {
        while (true)
        {
            laserFire();
            yield return new WaitForSeconds(projectileFiringPeriod);
        }
    }

    private void laserFire()
    {
        GameObject laser = Instantiate(
                laserPrefab,
                transform.position,
                Quaternion.identity) as GameObject;
        laser.GetComponent<Rigidbody2D>().velocity = new Vector2(0, projectileSpeed);
        AudioSource.PlayClipAtPoint(playerLaserSFX, Camera.main.transform.position, laserSoundVolume);
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
        if (!damageDealer) { return; }
        ProcessHit(damageDealer);
        AudioSource.PlayClipAtPoint(impactSound, Camera.main.transform.position, impactSoundVolume);
        GameObject impact = Instantiate(impactFX, transform.position, transform.rotation) as GameObject;
        Destroy(impact, 5f);
    }

    private void ProcessHit(DamageDealer damageDealer)
    {
        health -= damageDealer.GetDamage();
        damageDealer.Hit();
        if (health <= 0)
        {
            Die();
        }
    }

    private void Die()
    {
        //FindObjectOfType<SceneLoader>().LoadGameOver();
        GameOver();
        Destroy(gameObject);
        AudioSource.PlayClipAtPoint(deathPlayerSound, Camera.main.transform.position, deathSoundVolume);
        GameObject explosion = Instantiate(explosionPlayer, transform.position, transform.rotation) as GameObject;
        Destroy(explosion, 0.25f);
    }

    public void GameOver()
    {
        StartCoroutine(EndGame());
    }

    IEnumerator EndGame()
    {
        yield return new WaitForSeconds(WaitTime);
        SceneManager.LoadScene("GameOver");
    }
}

I think the problem is Destroy(gameObject); in Die(). At the end of the frame, the entire game object will get destroyed. This means that the coroutine will get terminated. If you need to destroy the game object, move the line to EndGame after the line with WaitForSeconds.

Test that and let me know if your solution works.

Thanks Nina! It did in fact seem to be the Destroy(gameObject).

Did you test what I suggested? And does your modified solution work? Or did you replace yours with Rick’s?


See also:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms