Search Unity

Checkpoint respawn not working correctly

Discussion in 'Scripting' started by DustyShinigami, Jul 16, 2019.

  1. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Okay, so I've managed to narrow down the culprit that's causing this bug, but I'm not sure what I should do to get rid of it for good. Basically, since getting my HealthManager to survive between levels using DontDestroyOnLoad, it seems to be preventing my checkpoint respawn from working correctly. The player should be able to hit a checkpoint, the position is saved, and when the player dies they're returned to that spot.

    I need my HealthManager to survive between scenes, but it's causing my player to respawn back at the start of the level instead. Now, I'm guessing it's because the startPosition and startRotation in the Start function are applied and carrying over from the previous scene...?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class HealthManager : MonoBehaviour
    8. {
    9.     //The counters will count down and will keep counting down based on the length variables
    10.     public int maxHealth;
    11.     public int currentHealth;
    12.     public float invincibilityLength;
    13.     public float flashLength;
    14.     public float respawnLength;
    15.     public GameObject deathEffect;
    16.     public Image blackScreen;
    17.     public float fadeSpeed;
    18.     public float waitForFade;
    19.     public Image flame1;
    20.     public Image flame2;
    21.     public Image flame3;
    22.     public Sprite fullFlame;
    23.     //public Sprite threeQuarterFlame;
    24.     public Sprite halfFlame;
    25.     //public Sprite quarterFlame;
    26.     public Sprite EmptyFlame;
    27.     public PlayerController thePlayer
    28.     {
    29.         get
    30.         {
    31.             if (_thePlayer != null)
    32.                 return _thePlayer;
    33.  
    34.             _thePlayer = GameObject.FindWithTag("Player")?.GetComponentInChildren<PlayerController>();
    35.             return _thePlayer;
    36.         }
    37.     }
    38.     public GameManager theGameManager;
    39.  
    40.     //This checks to see if there's a renderer on the player and if not, it finds and gets it
    41.     public SkinnedMeshRenderer playerRenderer
    42.     {
    43.         get
    44.         {
    45.             if (_playerRenderer != null)
    46.                 return _playerRenderer;
    47.  
    48.             _playerRenderer = GameObject.FindWithTag("Player")?.GetComponentInChildren<SkinnedMeshRenderer>();
    49.             Debug.Assert(playerRenderer != null);
    50.             return _playerRenderer;
    51.         }
    52.     }
    53.  
    54.     private float invincibilityCounter;
    55.     private float flashCounter;
    56.     private bool isRespawning;
    57.     private Vector3 respawnPoint;
    58.     private bool isFadetoBlack;
    59.     private bool isFadefromBlack;
    60.     private Quaternion startPosition;
    61.     private SkinnedMeshRenderer _playerRenderer = null;
    62.     private PlayerController _thePlayer = null;
    63.  
    64.     void Start()
    65.     {
    66.         currentHealth = maxHealth;
    67.         respawnPoint = thePlayer.transform.position;
    68.         startPosition = thePlayer.transform.rotation;
    69.     }
    70.  
    71.     void Update()
    72.     {
    73.         //These functions are checked every frame until the player takes damage
    74.         if (invincibilityCounter > 0)
    75.         {
    76.             invincibilityCounter -= Time.deltaTime;
    77.             flashCounter -= Time.deltaTime;
    78.             if (flashCounter <= 0)
    79.             //The Flash Counter is currently set at 0.1 and will be within the 0 region as it counts down. During this period, the playerRenderer will alternate between on and off
    80.             {
    81.                 playerRenderer.enabled = !playerRenderer.enabled;
    82.                 //The Flash Counter will keep counting down and reloop depending on the Flash Length time
    83.                 flashCounter = flashLength;
    84.             }
    85.             //This makes sure after the flashing and invincibility has worn off that the player renderer is always turned back on so you can see the player
    86.             if (invincibilityCounter <= 0)
    87.             {
    88.                 playerRenderer.enabled = true;
    89.             }
    90.         }
    91.         if (isFadetoBlack)
    92.         {
    93.             blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 1f, fadeSpeed * Time.deltaTime));
    94.             if (blackScreen.color.a == 1f)
    95.             {
    96.                 isFadetoBlack = false;
    97.             }
    98.         }
    99.         if (isFadefromBlack)
    100.         {
    101.             blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 0f, fadeSpeed * Time.deltaTime));
    102.             if (blackScreen.color.a == 0f)
    103.             {
    104.                 isFadefromBlack = false;
    105.             }
    106.         }
    107.     }
    108.  
    109.     public void HurtPlayer(int damage, Vector3 direction)
    110.     {
    111.         //If the invincibility countdown reaches zero it stops, making you no longer invincible and prone to taking damage again
    112.         if (invincibilityCounter <= 0)
    113.         {
    114.             currentHealth -= damage;
    115.             FlameMetre();
    116.             if (currentHealth <= 0)
    117.             {
    118.                 Respawn();
    119.             }
    120.             else
    121.             {
    122.                 thePlayer.Knockback(direction);
    123.                 invincibilityCounter = invincibilityLength;
    124.                 playerRenderer.enabled = false;
    125.                 flashCounter = flashLength;
    126.             }
    127.         }
    128.     }
    129.  
    130.     public void Respawn()
    131.     {
    132.         //A StartCoroutine must be set up before the IEnumerator can begin
    133.         if (!isRespawning)
    134.         {
    135.  
    136.             StartCoroutine("RespawnCo");
    137.         }
    138.     }
    139.  
    140.     //IEnumerators or Coroutines will execute the code separately at specified times while the rest of the code in a codeblock will carry on executing as normal
    141.     public IEnumerator RespawnCo()
    142.     {
    143.         if (!Checkpoint.checkpointActive)
    144.         {
    145.             isRespawning = true;
    146.             thePlayer.gameObject.SetActive(false);
    147.             Instantiate(deathEffect, thePlayer.transform.position, thePlayer.transform.rotation);
    148.             yield return new WaitForSeconds(respawnLength);
    149.             isFadetoBlack = true;
    150.             yield return new WaitForSeconds(waitForFade);
    151.             isFadefromBlack = true;
    152.             isRespawning = false;
    153.             thePlayer.gameObject.SetActive(true);
    154.             currentHealth = maxHealth;
    155.             invincibilityCounter = invincibilityLength;
    156.             playerRenderer.enabled = false;
    157.             flashCounter = flashLength;
    158.             SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    159.             FlameMetre();
    160.             GameManager.currentEmbers = 0;
    161.             theGameManager.SetCountText();
    162.         }
    163.  
    164.         else if (Checkpoint.checkpointActive)
    165.         {
    166.             isRespawning = true;
    167.             thePlayer.gameObject.SetActive(false);
    168.             Instantiate(deathEffect, thePlayer.transform.position, thePlayer.transform.rotation);
    169.             yield return new WaitForSeconds(respawnLength);
    170.             isFadetoBlack = true;
    171.             yield return new WaitForSeconds(waitForFade);
    172.             isFadefromBlack = true;
    173.             isRespawning = false;
    174.             thePlayer.gameObject.SetActive(true);
    175.             thePlayer.transform.position = respawnPoint;
    176.             thePlayer.transform.rotation = startPosition;
    177.             currentHealth = maxHealth;
    178.             FlameMetre();
    179.             invincibilityCounter = invincibilityLength;
    180.             playerRenderer.enabled = false;
    181.             flashCounter = flashLength;
    182.         }
    183.     }
    184.  
    185.     public void FlameMetre()
    186.     {
    187.         switch (currentHealth)
    188.         {
    189.             case 30:
    190.                 flame1.sprite = fullFlame;
    191.                 flame2.sprite = fullFlame;
    192.                 flame3.sprite = fullFlame;
    193.                 return;
    194.             case 25:
    195.                 flame1.sprite = fullFlame;
    196.                 flame2.sprite = fullFlame;
    197.                 flame3.sprite = halfFlame;
    198.                 return;
    199.             case 20:
    200.                 flame1.sprite = fullFlame;
    201.                 flame2.sprite = fullFlame;
    202.                 flame3.sprite = EmptyFlame;
    203.                 return;
    204.             case 15:
    205.                 flame1.sprite = fullFlame;
    206.                 flame2.sprite = halfFlame;
    207.                 flame3.sprite = EmptyFlame;
    208.                 return;
    209.             case 10:
    210.                 flame1.sprite = fullFlame;
    211.                 flame2.sprite = EmptyFlame;
    212.                 flame3.sprite = EmptyFlame;
    213.                 return;
    214.             case 5:
    215.                 flame1.sprite = halfFlame;
    216.                 flame2.sprite = EmptyFlame;
    217.                 flame3.sprite = EmptyFlame;
    218.                 return;
    219.             case 0:
    220.                 flame1.sprite = EmptyFlame;
    221.                 flame2.sprite = EmptyFlame;
    222.                 flame3.sprite = EmptyFlame;
    223.                 return;
    224.  
    225.             default:
    226.                 flame1.sprite = EmptyFlame;
    227.                 flame2.sprite = EmptyFlame;
    228.                 flame3.sprite = EmptyFlame;
    229.                 return;
    230.         }
    231.     }
    232.  
    233.     public void HealPlayer(int healAmount)
    234.     {
    235.         currentHealth += healAmount;
    236.         if(currentHealth > maxHealth)
    237.         {
    238.             currentHealth = maxHealth;
    239.         }
    240.     }
    241.  
    242.     public void SetSpawnPoint(Vector3 newPosition)
    243.     {
    244.         respawnPoint = newPosition;
    245.     }
    246. }
    If I comment those lines out, the player doesn't respawn anywhere, but instead just falls through the world. I'm not entirely sure what I could/should do to rectify this issue. An 'if' statement maybe...?
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
  3. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Okay, after looking into activeSceneChanged I came across delegates and events in that link you provided. Are those required when using activeSceneChanged? I've been trying to study and understand how to implement them properly and it's confusing me a bit.