(Unity C#) NullReferenceException 仅在 Start() 函数之外

(Unity C#) NullReferenceException ONLY outside of the Start() function

我一直收到错误消息:

NullReferenceException: Object reference not set to an instance of an object

这让我明白了:

if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, enemy.groundCheckDistance))

我做了一些测试,发现 enemy 实际上设置为这个对象的实例,因为我打印了 [=46= 的值] 每次更新,它每次都成功地从 enemy 对象中打印出正确的值。我什至在检查器中更改了它,它检索到了正确的值。 后来我发现我在 Start() 方法中设置的所有对象都变为 null 仅在 Start() 方法。 (我的意思是 Animator、Rigidbody、Capsule Collider 等都变为 null) 我是100% 确定动画师、胶囊对撞机、刚体和敌人已附加到此游戏对象。但是,我在 Awake() 上以不同的 class 创建它们。这就是我收到错误的原因吗?如果是我该如何解决?

这是我在 Awake() 上添加组件的脚本。当我 运行 游戏时,我看到它们已成功添加。

using UnityEngine;
using UnityEngine.AI;

namespace MGCO.Characters.EnemyScripts
{
    //USED TO CONSTRUCT THE COMPONENTS ON AN ENEMY AT RUNTIME
    public class EnemyComponents : MonoBehaviour
    {
        //INITIALIZE ENEMY OBJECT
        Enemy enemy;

        void Awake()
        {
            enemy = GetComponent<Enemy>();

            //MAKE SURE ENEMY IS NOT HUMANOID
            if (!enemy.isHumanoid)
            {
                //CHECK TO SEE IF MESH FILTER ALREADY EXISTS
                if (!GetComponent<MeshFilter>())
                {
                    //INITIALIZE "MeshFilter"
                    MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();

                    //SET MESH OF MESHFILTER
                    meshFilter.mesh = enemy.enemyMesh;
                }

                //CHECK TO SEE IF MESH RENDERER ALREADY EXISTS
                if (!GetComponent<MeshRenderer>())
                {
                    //INITIALIZE "MeshRenderer"
                    MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();

                    //SET MESH MATERIAL
                    meshRenderer.material = enemy.meshMaterial;
                }
            }
            //MAKE SURE ENEMY IS NOT HUMANOID
            else
            {
                //CHECK TO SEE IF ANIMATOR ALREADY EXISTS
                if (!GetComponent<Animator>())
                {
                    //INITIALIZE "RuntimeAnimatorController"
                    Animator animator = gameObject.AddComponent<Animator>();

                    //SET RUNTIMEANIMATORCONTROLLER
                    animator.runtimeAnimatorController = enemy.runtimeAnimatorController;

                    //SET AVATAR
                    animator.avatar = enemy.avatar;

                    //SET ROOT ANIMATION BOOL
                    animator.applyRootMotion = enemy.applyRootMotion;
                }
            }

            //CHECK TO SEE IF RIGIDBODY ALREADY EXISTS
            if (!GetComponent<Rigidbody>())
            {
                //INITIALIZE "Rigidbody"
                Rigidbody enemyRigidbody = gameObject.AddComponent<Rigidbody>();

                //SET MASS
                enemyRigidbody.mass = enemy.mass;

                //SET DRAG
                enemyRigidbody.drag = enemy.drag;

                //SET ANGULAR DRAG
                enemyRigidbody.angularDrag = enemy.angularDrag;

                //SET USE GRAVITY
                enemyRigidbody.useGravity = enemy.useGravity;
            }

            //CHECK TO SEE IF NAVMESHAGENT ALREADY EXISTS
            if (!GetComponent<NavMeshAgent>())
            {
                //INITIALIZE "NavMeshAgent"
                NavMeshAgent navMeshAgent = gameObject.AddComponent<NavMeshAgent>();

                //SET NAVMESH SPEED
                navMeshAgent.speed = enemy.speed;

                //SET BASE OFFSET
                navMeshAgent.baseOffset = enemy.baseOffset;

                //SET ANGULAR SPEED (HOW FAST ENEMY TURNS CORNERS)
                navMeshAgent.angularSpeed = enemy.angularSpeed;

                //SET ACCELERATION
                navMeshAgent.acceleration = enemy.acceleration;

                //SET STOPPING DISTANCE
                navMeshAgent.stoppingDistance = enemy.stoppingDistance;

                //SET OBSTACLE AVOIDANCE RADIUS
                navMeshAgent.radius = enemy.navmeshRadius;

                //SET OBSTACLE AVOIDANCE HEIGHT
                navMeshAgent.radius = enemy.navmeshHeight;
            }

            //CHECK TO SEE IF COLLIDER ALREADY EXISTS
            if (!GetComponent<CapsuleCollider>())
            {
                //INITIALIZE "CapsuleCollider"
                CapsuleCollider capsuleCollider = gameObject.AddComponent<CapsuleCollider>();

                //SET CENTER
                capsuleCollider.center = enemy.center;

                //SET COLLIDER RADIUS
                capsuleCollider.radius = enemy.colliderRadius;

                //SET COLLIDER HEIGHT
                capsuleCollider.height = enemy.colliderHeight;
            }
        }
    }
}

这是出现错误的脚本:

using UnityEngine;

namespace MGCO.Characters.EnemyScripts
{
    public class EnemyAnimation : MonoBehaviour
    {
        //REFERENCE GAMEOBJECTS
        Enemy enemy;
        Animator animator;
        Rigidbody enemyRigidbody;
        CapsuleCollider capsuleCollider;


        //INITIALIZE VARS
        Vector3 groundNormal;
        Vector3 capsuleCenter;

        private bool isCrouching;
        private bool isGrounded;

        private float originalGroundCheckDistance;
        private float turnAmount;
        private float forwardAmount;
        private float capsuleHeight;

        //VALUE FOR HALF (NEVER CHANGES)
        const float half = 0.5f;

        //RUNS ON START
        void Start()
        {
            enemy = GetComponent<Enemy>();

            animator = GetComponent<Animator>();
            enemyRigidbody = GetComponent<Rigidbody>();
            capsuleCollider = GetComponent<CapsuleCollider>();
            capsuleHeight = capsuleCollider.height;
            capsuleCenter = capsuleCollider.center;

            //FREEZE RIGIDBODY ROTATION
            enemyRigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
            //SET LOCAL VARIABLE
            originalGroundCheckDistance = enemy.groundCheckDistance;
        }

        ...

        //CHECKS POSITION OF GROUND BENEATH PLAYER
        void CheckGroundStatus()
        {
            //INITIALIZE RAYCASTHIT
            RaycastHit hitInfo;

            //IF RAYCASTS DOWN TO "GroundCheckDistance" VARIABLE
            if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, enemy.groundCheckDistance))
            {
                //SET GROUNDNORMAL TO THE SURFACE OF THE RAYCASTHIT
                groundNormal = hitInfo.normal;
                //SET JUMPING FALSE
                isGrounded = true;
                //ANIMATOR APPLY ROOT MOTION
                animator.applyRootMotion = true;
            }
            else
            {
                //SET JUMPING TO TRUE
                isGrounded = false;
                //SET GROUNDNORMAL TO GO UP
                groundNormal = Vector3.up;
                //ANIMATOR DO NOT APPLY ROOT MOTION
                animator.applyRootMotion = false;
            }
        }
    }
}

感谢您的帮助:)

//REFERENCE GAMEOBJECTS  
Enemy enemy;  
Animator animator;  
Rigidbody enemyRigidbody;  
CapsuleCollider capsuleCollider;

在这里你声明了你的引用,但你没有在任何地方分配它们。

Rigidbody enemyRigidbody = gameObject.AddComponent<Rigidbody>();

在这里,您添加了刚体组件,它 returns 是对自身的引用。但是,您将引用分配给了一个名为 enemyRigidbody 的不同变量,而不是上面声明的变量。

即使变量名称相似,在较小的 scope/declaration space 中声明一个变量(一个在 class 中,另一个在一个方法中)会创建一个全新的变量名称相同,但只能在方法本身内使用。

你想要的是:

enemyRigidbody = gameObject.AddComponent<Rigidbody>();

这是对您在上面声明的 Rigidbody 的引用。