Вектор3 сбрасывается до 0,0,0 единицы

#c# #unity3d #nullreferenceexception #qvector3d

#c# #unity3d #исключение nullreferenceexception #qvector3d

Вопрос:

Прямо сейчас я создаю игру, в которой враги становятся предупрежденными об игроке и преследуют их неопределенно долго, пока игрок не встанет на «безопасную тарелку» в игре. Когда игрок стоит здесь, враги должны вернуться в исходное положение.

Проблема в том, что всякий раз, когда игрок стоит на тарелке, я получаю ошибку исключения нулевой ссылки, и я вижу, что исходная позиция защиты была сброшена на 0,0,0 в консоли. Я предполагаю, что причина исключения нулевой ссылки заключается в том, что мировое происхождение не находится в используемой мной навигационной сетке, хотя я легко могу ошибаться в этом. Я просто не могу понять, почему значение vector3 вообще изменилось, поскольку переменная guardPosition инициируется при запуске и больше никогда не трогается.

Я включил как мой класс enemyAi (скрипт, прикрепленный к enemy), так и мой класс, связанный с наступлением на тарелки. Если есть что-то еще, что нужно включить, дайте мне знать. Если у кого-нибудь есть какие-либо идеи, буду признателен за помощь. Приветствия.

Скриншот на консоли после нажатия на тарелку

 public class EnemyAI : MonoBehaviour
{
    
    DeathHandler dh;

    [SerializeField] Transform target;
    [SerializeField] float chaseRange = 5f;
    [SerializeField] float killRange = 2f;

    [SerializeField] GameObject explosionEffect;

    NavMeshAgent navMeshAgent;
    float distanceToTarget = Mathf.Infinity;
    bool isDead = false;
    bool isAlert = false;

    Vector3 guardPosition;

    void Start()
    {
        GameObject gob;
        gob = GameObject.Find("Player");
        dh = gob.GetComponent<DeathHandler>();

        guardPosition = transform.position;

        navMeshAgent = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        distanceToTarget = Vector3.Distance(target.position, transform.position);

        print(guardPosition   " guard position during update");

        //alert a dude
        if (distanceToTarget <= chaseRange amp;amp; !isDead)
        {
            isAlert = true;
        }

        //chase a dude
        if (isAlert == true)
        {
            ChasePlayer();
            print(isAlert);
        }
    }

    public void ChasePlayer()
    {
        navMeshAgent.SetDestination(target.position);

        //explode a dude
        if (distanceToTarget <= killRange)
        {
            Explode();
            dh.KillPlayer();
        }
    }

    public void SetAlertStatus(bool status)
    {
        isAlert = status;
    }

    public void ReturnToPost()
    {
        //isAlert = false;
        print(guardPosition   " guard position after stepping on plate");
        navMeshAgent.SetDestination(guardPosition);
    }    

    void Explode()
    {
        Instantiate(explosionEffect, transform.position, transform.rotation);

        isDead = true;
        Destroy(gameObject);
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, chaseRange);
    }
}
 
 public class SafeSpots : MonoBehaviour
{
    
EnemyAI enemyAi;

    

    void Start()
    {
        GameObject gob;
        gob = GameObject.FindGameObjectWithTag("Enemy");
        enemyAi = gob.GetComponent<EnemyAI>();
    }

    public void OnTriggerStay(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
            

            enemyAi.SetAlertStatus(false);
            enemyAi.ReturnToPost();
        }
    }
}
 

Комментарии:

1. вы уверены, что извлекаете navMeshAgent данные в начале? Возможно, это то, что равно нулю и является причиной исключения

2. Насколько я знаю, он извлекается. Враг будет преследовать игрока на NavMesh fine. Это просто, когда игрок наступает на тарелку, она ломается.

3. код не выдает описанное поведение — ни одна строка не выводит «защитную позицию во время обновления». В любом случае, возможно, что EnemyAI.guardPosition считываемый для печати журнал «положение защиты во время обновления» имеет экземпляр EnemyAI , отличный от FindGameObjectWithTag("Enemy") найденного. В вопросе упоминается много врагов. Рассматривали ли вы возможность использования FindGameObjectsWithTag затем перебора их всех?

4. Ах, извините, я изменил операторы печати после вставки кода, чтобы сделать снимок экрана более читаемым. Теперь я отредактировал код до того места, где они появляются. Что касается вашего предложения, у меня действительно есть несколько врагов, но в целях тестирования я отключил скрипт EnemyAi для всех, кроме 1.

5. Да, и поэтому, когда вы ищете игровые объекты с тегом in SafeSpots.Start , кажется, что он получает тот, у которого EnemyAI отключен скрипт. И поскольку он отключен, он EnemyAI.Start не запускается, и поэтому он guardPosition = transform.position; никогда не вызывается в этом экземпляре. Это означает, что когда вы вызываете GetComponent<EnemyAI>() его, он получает отключенный экземпляр EnemyAI , который никогда не устанавливал свое guardPosition поле. Это другой экземпляр EnemyAI , чем тот, который Update выполняется и печатает «защитную позицию во время обновления»

Ответ №1:

Вы получаете отключенный экземпляр EnemyAI . Вместо этого используйте FindGameObjectsWithTag затем перебирайте их все и добавляйте их EnemyAI в список, который вы можете перебирать при необходимости. Кстати, его лучше использовать CompareTag , когда это возможно, для уменьшения мусора:

 public class SafeSpots : MonoBehaviour
{
    
    List<EnemyAI> enemyAis;

    void Start()
    {
        GameObject[] enemies= GameObject.FindGameObjectsWithTag("Enemy");
        enemyAis = new List<EnemyAI>();
       
        foreach (GameObject enemy in enemies)
        {
            enemyAis.Add(enemy.GetComponent<EnemyAI>());
        }
    }

    public void OnTriggerStay(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            foreach(EnemyAI enemyAi in enemyAis)
            {
                enemyAi.SetAlertStatus(false);
                enemyAi.ReturnToPost();
            }
        }
    }
}
 

Комментарии:

1. Да, хорошо, так оно и было! Все это время я фокусировался не на той области. Я внес эти изменения, и теперь я получаю ожидаемое поведение. Большое вам спасибо, это сводит меня с ума. Я буду помнить об этом CompareTag и в будущем, спасибо!