Null Reference

Hi,
I’m having troubles with null reference exception when i try to load it shows this message

NullReferenceException: Object reference not set to an instance of an object
RPG.Combat.Fighter.EquipWeapon (RPG.Combat.Weapon weapon) (at Assets/Scripts/Combat/Fighter.cs:49)
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
using RPG.Saving;
using RPG.Attributes;


namespace RPG.Combat
{
    public class Fighter : MonoBehaviour, IAction, ISaveable
{
    [SerializeField] float timeBetweenAttacks = .5f;
    [SerializeField] Transform rightHandTransform = null;
    [SerializeField] Transform leftHandTransform = null;
    [SerializeField] Weapon defaultWeapon = null;

    Health target; 
    float timeSinceLastAttack = Mathf.Infinity;
    Weapon currentWeapon = null; 


    private void Awake() 
    {
            if (currentWeapon == null)
            {
                EquipWeapon(defaultWeapon);
            }
        }

        private void Update()
        {
            timeSinceLastAttack += Time.deltaTime;
            if (target == null) return;
            if (target.IsDead()) return;
            if (!GetIsInRange())
            {
                GetComponent<Mover>().MoveTo(target.transform.position, 1f);
            }
            else
            {
                GetComponent<Mover>().Cancel();
                AttackBehaviour();
            }
        }
        public void EquipWeapon(Weapon weapon)
        {
            currentWeapon = weapon;
            Animator animator = GetComponent<Animator>();
            weapon.Spawn(rightHandTransform, leftHandTransform, animator);
        }

        public Health GetTarget()
        {
            return target;
        }

        private void AttackBehaviour()
        {
            transform.LookAt(target.transform);
            if (timeSinceLastAttack > timeBetweenAttacks)
            {
                // This will trigger the Hit() event.
                TriggerAttack();
                timeSinceLastAttack = 0;
            }
        }
        private void TriggerAttack()
        {
            GetComponent<Animator>().ResetTrigger("stopAttack");
            GetComponent<Animator>().SetTrigger("attack");
        }
        // Animation Event
        void Hit()
        {
            if(target == null) { return; }
            
            if (currentWeapon.HasProjectile())
            {
                currentWeapon.LaunchProjectile(rightHandTransform, leftHandTransform, target, gameObject);
            }
            else
            {
                target.TakeDamage(gameObject, currentWeapon.GetDamage());
            }
        }
        void Shoot()
        {
            Hit();
        }
        private bool GetIsInRange()
        {
            return Vector3.Distance(transform.position, target.transform.position) < currentWeapon.GetRange();
        }
        public bool CanAttack(GameObject combatTarget)
        {
            if (combatTarget == null) { return false; }
            Health targetToTest = combatTarget.GetComponent<Health>();
            return targetToTest != null && !targetToTest.IsDead();
        }
        public void Attack(GameObject combatTarget)
        {
            GetComponent<ActionScheduler>().StartAction(this);
            target = combatTarget.GetComponent<Health>();
        }
        public void Cancel()
        {
            StopAttack();
            target = null;
            GetComponent<Mover>().Cancel();
        }
        private void StopAttack()
        {
            GetComponent<Animator>().ResetTrigger("attack");
            GetComponent<Animator>().SetTrigger("stopAttack");
        }

        public object CaptureState()
        {
            return currentWeapon.name;
        }

        public void RestoreState(object state)
        {
            string weaponName = (string) state;
        Debug.Log($"RestoreState - {weaponName}");
            Weapon weapon = Resources.Load<Weapon>(weaponName);
            if(weapon == null)
            {
                Debug.Log($"The weapon was not found in Resources");
            }
            EquipWeapon(weapon);
            
        }

    }
}

Looks like you’ve got a null reference exception on line 49 of your fighter script.

Your null reference is in the EquipWeapon method, specifically, when we ask the weapon to spawn a model.

There should be more to the error message, and the balance of the error message is what we call a stack trace. It shows us the methods that called the method where the error occurred.

In this case we know that the weapon being passed to EquipWeapon is null. There are a couple of scripts that call EquipWeapon, but only two are possible when you start the game…

If the line immediately under the error line you posted has Fighter.Awake() at line xx, then the defaultWeapon hasn’t been set in the inspector. Check all of your characters and make sure there is a default Weapon assigned.

If the line immediately under the error line you posted has Fighter.RestoreState() at line xx, then when RestoreState tried to restore the weapon, it got a null result. This is most likely because the Weapon ScriptableObject is not in a folder named Resources (Case and spelling matters).

1 Like

Sorry this is the full error code, I have checked that all characters in the scene have the a default weapon assigned and checked the case sensitive Resources folder with the weapons in it.

NullReferenceException: Object reference not set to an instance of an object
RPG.Combat.Fighter.EquipWeapon (RPG.Combat.Weapon weapon) (at Assets/Scripts/Combat/Fighter.cs:50)
RPG.Combat.Fighter.RestoreState (System.Object state) (at Assets/Scripts/Combat/Fighter.cs:132)
RPG.Saving.SaveableEntity.RestoreState (System.Object state) (at Assets/Scripts/Saving/SaveableEntity.cs:39)
RPG.Saving.SavingSystem.RestoreState (System.Collections.Generic.Dictionary`2[TKey,TValue] state) (at Assets/Scripts/Saving/SavingSystem.cs:85)
RPG.Saving.SavingSystem.Load (System.String saveFile) (at Assets/Scripts/Saving/SavingSystem.cs:35)
RPG.SceneManagement.SavingWrapper.Load () (at Assets/Scripts/SceneManagement/SavingWrapper.cs:38)
RPG.SceneManagement.SavingWrapper.Update () (at Assets/Scripts/SceneManagement/SavingWrapper.cs:25)

Ok, so the issue is definitely in the CaptureState/RestoreState.

Paste in your CaptureState and RestoreState methods from Fighter.cs and we’ll take a look. I’ll likely add some Debugs after you’ve pasted them in

Thank you for taking the time to look into this.

        public object CaptureState()
        {
            return currentWeapon.name;
        }

        public void RestoreState(object state)
        {
            string weaponName = (string)state;
            Weapon weapon = Resources.Load<Weapon>(weaponName);
            EquipWeapon(weapon);
        }

Let’s add a couple of debugs here to see if we can get an idea what’s going on:

public object CaptureState()
{
    Debug.Log($"{name} is returning {currentWeapon.name} to CaptureState.");
    return currentWeapon.name;
}

public void RestoreState(object state)
{
    string weaponName = string(state);
    Debug.Log($"{name} is attempting to restore {weaponName}");
    Weapon weapon = Resources.Load<Weapon>(weaponName);
    if(weapon==null) 
    {
          Debug.Log($"{weaponName} does not appear to exist in a Resources folder");
          return;
     }
     EquipWeapon(weapon);
}
1 Like

Privacy & Terms