Home > Back-end >  Restarting game upon player death is deleting game objects
Restarting game upon player death is deleting game objects

Time:12-05

I am in the process of creating a call of duty zombies style game. The issue I'm currently running into is when my player's health = 0 the game restarts but for some reason throws out the following errors:

MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it.

Your script should either check if it is null or you should not destroy the object.

UnityEngine.Transform.get_position () (at <bae255e3e08e46f7bc2fbd23dde96338>:0)

Gun.Shoot () (at Assets/Scripts/Gun.cs:55)

PlayerShoot.Update () (at Assets/Scripts/PlayerShoot.cs:16)

I am using the unity scene management function and when my player's health reaches 0 I run the code:

Debug.Log("Dead");
            SceneManager.LoadScene("Zombie Game");

Nowhere in the Gun script or the Player Shoot script is there anything about destroying any game objects or transforms on death.

PlayerShoot Script:

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

public class PlayerShoot : MonoBehaviour {

    public static Action shootInput;
    public static Action reloadInput;

    [SerializeField] private KeyCode reloadKey = KeyCode.R;

    private void Update()
    {
        if (Input.GetMouseButton(0))
            shootInput?.Invoke();

        if (Input.GetKeyDown(reloadKey))
            reloadInput?.Invoke();
    }
}

Gun Script:

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

public class Gun : MonoBehaviour {


    Ray ray; // the ray with origin amd direction for the cast
    float distance; // if needed a maximum distance
    LayerMask layers; // the general raycast layer - not different ones for each player ;)
    GameObject Player; // your player object
    


    [Header("References")]
    [SerializeField] private GunData gunData;
    [SerializeField] private Transform cam;
    
    float timeSinceLastShot;
        

    public void Start() {
        PlayerShoot.shootInput  = Shoot;
        PlayerShoot.reloadInput  = StartReload;
        
    }

    public void OnDisable() => gunData.reloading = false;

    public void StartReload() {
        if (!gunData.reloading && this.gameObject.activeSelf)
            StartCoroutine(Reload());
    }

    private IEnumerator Reload() {
        gunData.reloading = true;

        yield return new WaitForSeconds(gunData.reloadTime);

        gunData.currentAmmo = gunData.magSize;

        gunData.reloading = false;
    }

    public bool CanShoot() => !gunData.reloading && timeSinceLastShot > 1f / (gunData.fireRate / 60f);

    public void Shoot() {
        
        if (gunData.currentAmmo > 0) {
            if (CanShoot()) 
            {
                
                if (Physics.Raycast(cam.position, cam.forward, out RaycastHit hitInfo, gunData.maxDistance))
                {
                    IDamageable damageable = hitInfo.transform.GetComponent<IDamageable>();
                    damageable?.TakeDamage(gunData.damage);
                    
                }

                gunData.currentAmmo--;
                timeSinceLastShot = 0;
                OnGunShot();

            }
        }

        

    }

    public void Update() 
    
    {
        timeSinceLastShot  = Time.deltaTime;

        Debug.DrawRay(cam.position, cam.forward * gunData.maxDistance);

        
    }

    public void OnGunShot() {}

    

   
      }

I am New to coding, so this as been a tough one for me to try and work out.

I feel confident that the issue has something to do with the player transform or the ray cast, but I have no idea what I can do to prevent this error from occurring when the game is reset.

Any help would be HUGELY appreciated.

CodePudding user response:

When you're calling SceneManager.LoadScene("Zombie Game") to reload your scene. This effectively destroys the objects in the scene which do not have a DontDestroyOnLoad attribute.

It is generally good practice to unsubscribe from events when an object is destroyed. This is because events are a type of delegate, a reference to a method that can be called later. If you do not unsubscribe from an event, the delegate will continue to reference the method, even if the object registered for the event is destroyed.

This can cause problems if the event is triggered after the object is destroyed, as the delegate will still try to call the method on the destroyed object. This can result in errors or exceptions being thrown, depending on the event's implementation and the method it calls.

To avoid these problems, it is recommended to unsubscribe from events in the OnDestroy() method of the registered object for the event. This ensures that the delegate is no longer referencing the method on the object, and the event can be safely triggered without causing any errors:

public class Gun : MonoBehaviour {
    
    public void Start() {
        PlayerShoot.shootInput  = Shoot;
        PlayerShoot.reloadInput  = StartReload;
    }

    private void OnDestroy() {
        PlayerShoot.shootInput -= Shoot;
        PlayerShoot.reloadInput -= StartReload;
    }
}

You should also ensure that any references assigned through the inspector remain valid once your scene reloads.

  • Related