(Unity C #) NullReferenceException ТОЛЬКО вне функции Start () - PullRequest
0 голосов
/ 01 мая 2018

Я получаю сообщение об ошибке:

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))

Я провел некоторое тестирование и обнаружил, что враг на самом деле был установлен на экземпляр этого объекта, потому что я печатал значение для врага.groundCheckDistance каждое обновление, и оно успешно печаталось правильное значение от объекта врага каждый раз. Я даже изменил его в инспекторе, и он получил правильное значение. Позже я обнаружил, что все объекты, которые я установил в методе Start () , обращаются в нуль только вне метода Start () . (Под этим я подразумеваю, что аниматор, твердое тело, капсульный коллайдер и т. Д. Обнуляются) Тем не менее, я создаю их в Awake () в другом классе. Может быть, поэтому я получаю ошибку? Если это как я могу это исправить?

Это скрипт, в который я добавляю компоненты 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;
            }
        }
    }
}

И спасибо вам за помощь:)

1 Ответ

0 голосов
/ 01 мая 2018
//REFERENCE GAMEOBJECTS  
Enemy enemy;  
Animator animator;  
Rigidbody enemyRigidbody;  
CapsuleCollider capsuleCollider;

Здесь вы декларируете свои ссылки, но нигде их НЕ НАЗНАЧАЕТЕ.

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

Здесь вы добавляете компонент Hardbody, и он возвращает ссылку на себя. Тем не менее, вы присвоили ссылку на РАЗНУЮ переменную с именем враги, вместо той, которую вы объявили выше.

Несмотря на то, что имена переменных похожи, объявление переменной в меньшей области видимости / области объявления (одна в классе, другая в методе) создает совершенно новую переменную с тем же именем, но ТОЛЬКО ИСПОЛЬЗУЮЩАЯСЯ В МЕТОДЕ САМ.

То, что вы хотите:

enemyRigidbody = gameObject.AddComponent<Rigidbody>();

это ссылка на твердое тело, которое вы объявили выше.

...