Null Reference Exception while going through the portal

My fader never fades in when after loading the next scene. Please help. I have spent quite a lot of time on this but I couldn’t pinpoint a problem.

NullReferenceException: Object reference not set to an instance of an object
RPG.Combat.Weapon.Spawn (UnityEngine.Transform rightHandTransform, UnityEngine.Transform leftHandTransform, UnityEngine.Animator animator) (at Assets/Scripts/Combat/Weapon.cs:24)
RPG.Combat.Fighter.EquipWeapon (RPG.Combat.Weapon weapon) (at Assets/Scripts/Combat/Fighter.cs:53)
RPG.Combat.Fighter.RestoreState (System.Object state) (at Assets/Scripts/Combat/Fighter.cs:131)
RPG.Saving.SavableEntity.RestoreState (System.Object state) (at Assets/Scripts/Saving/SavableEntity.cs:42)
RPG.Saving.SavingSystem.RestoreState (System.Collections.Generic.Dictionary`2[TKey,TValue] state) (at Assets/Scripts/Saving/SavingSystem.cs:63)
RPG.Saving.SavingSystem.Load (System.String saveFile) (at Assets/Scripts/Saving/SavingSystem.cs:44)
RPG.SceneManagement.SavingWrapper.Load () (at Assets/Scripts/Saving/SavingWrapper.cs:33)
RPG.SceneManagement.Portal+d__7.MoveNext () (at Assets/Scripts/SceneManagement/Portal.cs:41)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at :0)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;
using RPG.Saving;

namespace RPG.Combat
{    
    public class Fighter : MonoBehaviour, IAction, ISaveable

    {
        [SerializeField] float timeBetweenAttacks = 0.5f;
        [SerializeField] Transform rightHandTransform = null;
        [SerializeField] Transform leftHandTransform = null;
        [SerializeField] Weapon defaultWeapon = null;

        float timeSinceLastAttack = Mathf.Infinity;
        Weapon currentWeapon = null;
        Transform target;
        Animator animator;
        Mover mover;
        private void Start()
        {
            mover = GetComponent<Mover>();
            animator = GetComponent<Animator>();
            if (currentWeapon == null)
            {
                EquipWeapon(defaultWeapon);
            }
        }
        private void Update()
        {
            timeSinceLastAttack += Time.deltaTime;
            if (target == null) return;
            if (target.GetComponent<Health>().IsDead()) return;
            if (!IsInRange())
            {
                mover.Moveto(target.position, 1);
            }
            else
            {
                mover.Cancel();
                AttackBehaviour();
            }
        }
        public void EquipWeapon (Weapon weapon)
        {
            if (currentWeapon != null) currentWeapon.DestroySpawnedGameObject();
            currentWeapon = weapon;
            if (currentWeapon == null) return;
            currentWeapon.Spawn(rightHandTransform, leftHandTransform, animator);
        }

        private void AttackBehaviour()
        {
            transform.LookAt(target);
            if (timeSinceLastAttack > timeBetweenAttacks)
            {
                TriggerAttack();
                timeSinceLastAttack = 0f;
            }
        }

        private void TriggerAttack()
        {
            animator.ResetTrigger("StopAttack");
            animator.SetTrigger("Attack");
        }

        public bool CanAttack(GameObject gameObject)
        {
            Health health = gameObject.transform.GetComponent<Health>();
            return health != null && !health.IsDead();
        }

        private bool IsInRange()
        {
            return Vector3.Distance(transform.position, target.position) <= currentWeapon.GetWeaponRange();
        }

        public void Attack(GameObject gameObject)
        {
            GetComponent<ActionScheduler>().StartAction(this);
            target = gameObject.transform;
        }
        public void Cancel()
        {
            StopAttackAnimation();
            mover.Cancel();
            target = null;
        }

        private void StopAttackAnimation()
        {
            animator.ResetTrigger("Attack");
            animator.SetTrigger("StopAttack");
        }

        //animation hit event
        public void Hit()
        {
            if (target == null) return;
            if (currentWeapon.HasProjectile())
            {
                currentWeapon.SpawnProjectile(rightHandTransform, leftHandTransform, target);
            }
            else
            {
                print("enemy taking damage");
                target.GetComponent<Health>().TakeDamage(currentWeapon.GetWeaponDamage());
            }
        }
        //animation hit event
        public void Shoot()
        {
            Hit();
        }

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

        public void RestoreState(object state)
        {
            string restoredWeaponName = (string)state;
            Weapon restoredWeapon = Resources.Load<Weapon>(restoredWeaponName);
            currentWeapon = restoredWeapon;
            EquipWeapon(restoredWeapon);
        }
    }
}

The error is in the Spawn of the Weapon script. The most likely cause is that the Fighter component on one of the characters in the new scene does not have it’s right and left hand transforms set. You’ll need to check each character in the scene you are trying to transition to and make sure the left and right hand transforms are set.

1 Like

I checked again. All characters in all scenes (I have only 2 scenes) have their hand transforms set. I additionally got the following error along with the previous error. Still can’t get it to work

MissingReferenceException: The object of type ‘GameObject’ 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.GameObject.GetComponent[T] () (at :0)
RPG.Cinematics.PlayerControlRemover.EnableControl (UnityEngine.Playables.PlayableDirector pd) (at Assets/Game/Cinematics/PlayerControlRemover.cs:26)
UnityEngine.Playables.PlayableDirector.SendOnPlayableDirectorStop () (at <7d902e83d7e6458bad82943edc23c3f0>:0)

That usually means you’re Instantiating an object instead of a prefab and it’s been destroyed before you spawn it.

But I am spawning from resources in the code

public void RestoreState(object state)
        {
            string restoredWeaponName = (string)state;
            Weapon restoredWeapon = Resources.Load<Weapon>(restoredWeaponName);
            currentWeapon = restoredWeapon;
            EquipWeapon(restoredWeapon);
        }

The reference here is inside PlayerControlRemover. Paste in the PlayerControlRemover script, and I’ll take a look.

using RPG.Control;
using RPG.Core;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

namespace RPG.Cinematics
{
    public class PlayerControlRemover : MonoBehaviour
    {
        GameObject player;
        void Start()
        {
            GetComponent<PlayableDirector>().played += DisableControl;
            GetComponent<PlayableDirector>().stopped += EnableControl;
            player = GameObject.FindWithTag("Player");
        }
        private void DisableControl(PlayableDirector pd)
        {
            player.GetComponent<ActionScheduler>().CancelCurrentAction();
            player.GetComponent<PlayerController>().enabled = false;
        }
        private void EnableControl(PlayableDirector pd)
        {
            player.GetComponent<PlayerController>().enabled = true;
        }
    }

}

The first error points to this line in the weapon script.

var ovverrideController = animator.runtimeAnimatorController as AnimatorOverrideController;

This is my weapon script

using UnityEngine;

namespace RPG.Combat
{
    [CreateAssetMenu(fileName = "Weapon", menuName = "Weapons/Create New Weapon", order = 0)]
    public class Weapon : ScriptableObject
    {
        [SerializeField] float weaponRange = 1.2f;
        [SerializeField] float weapondamage = 20;
        [SerializeField] GameObject equippedWeapon = null;
        [SerializeField] AnimatorOverrideController weaponOverrideController = null;
        [SerializeField] bool isRightHanded = false;
        [SerializeField] Projectile projectile;

        GameObject spawnedObject = null;

        public void Spawn (Transform rightHandTransform, Transform leftHandTransform, Animator animator)
        {
            if(equippedWeapon != null)
            {
                Transform handTransform = GetHandTransform(rightHandTransform, leftHandTransform);
                spawnedObject = Instantiate(equippedWeapon, handTransform);
            }
            var ovverrideController = animator.runtimeAnimatorController as AnimatorOverrideController;
            if (weaponOverrideController != null)
            {
                animator.runtimeAnimatorController = weaponOverrideController;
            }
            if (ovverrideController != null)
            {
                animator.runtimeAnimatorController = ovverrideController.runtimeAnimatorController;
            }
        }
        public void SpawnProjectile (Transform rightHandTransform, Transform leftHandTransform, Transform target)
        {
            if (projectile == null) return;
            Transform handTransform = GetHandTransform (rightHandTransform, leftHandTransform);
            Projectile projectileIstantiation = Instantiate(projectile, handTransform.position, Quaternion.identity);
            projectileIstantiation.SetTarget(target, weapondamage);
        }
        public bool HasProjectile()
        {
            return projectile != null;
        }
        private Transform GetHandTransform(Transform rightHandTransform, Transform leftHandTransform)
        {
            if (isRightHanded) return rightHandTransform;
            else return leftHandTransform;
        }
        public void DestroySpawnedGameObject()
        {
            if (spawnedObject == null) return;
            Destroy(spawnedObject);
        }
        public float GetWeaponRange()
        {
            return weaponRange;
        }
        public float GetWeaponDamage()
        {
            return weapondamage;
        }
    }
}

For the AnimatorRuntimeController line… it would appear that something is passing a null reference to to the Animator in Fighter… one of the charactes doesn’t have the animator set properly.
You can find which one by adding this line before the overrideController = animator.runtime…

if(animator==null)
{
     Debug.LogError($"{rightHandTransform.GetComponentInParent<Fighter>().gameObject.name} does not have the animator set correctly in it's Fighter component.");
     return;
}

I’ll take a closer look at the other error in the morning.

I moved the animator = GetComponent<Animator>(); line to awake() from start() and it resolved the issue.

I am not able to recreate the other error with regards to playerControlRemover.

Thank you guys for the help. Really appreciate it!

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

Privacy & Terms