В Unity2D GameObject создается, но не запускает то, что должен делать при столкновении (иногда) - PullRequest
0 голосов
/ 16 сентября 2018

У меня есть игровой объект здоровья, который может быть создан при уничтожении врага.Большую часть времени он лечит игрока, воспроизводит звуковые эффекты и т. Д. Другими словами, он ведет себя так, как он должен.Однако иногда (возможно, 1 из 10 раз) при столкновении с созданным объектом объект воспроизводит звуковой эффект, но не излечивает игрока и не уничтожается.Это сопровождается ошибкой:

MissingReferenceException: объект типа 'GameObject' был уничтожен, но вы все еще пытаетесь получить к нему доступ.Ваш скрипт должен либо проверять, является ли он нулевым, либо вы не должны уничтожать объект.UnityEngine.Object.Internal_InstantiateSingle (UnityEngine.Object data, Vector3 pos, Quaternion rot) UnityEngine.Object.Instantiate (UnityEngine.Object оригинал, позиция Vector3, кватернионное вращение) (в C: / buildslave / unity / build / Unity / RunEngOb / Runtime / Export.bindings.cs: 211) UnityEngine.Object.Instantiate [GameObject] (оригинал UnityEngine.GameObject, позиция Vector3, вращение кватернионов) (в C: /buildslave/unity/build/Runtime/Export/UnityEngineObject.bindings.cs: 285)Heart.OnTriggerEnter2D (столкновение UnityEngine.Collider2D) (в Assets / Scripts / Heart.cs: 36)

Я довольно долго пытался выяснить, что происходит, и я не могу точно определить,проблема.Под объектом работоспособности, на который указывает ошибка, (ошибка фактически указывает на строку, в которой создается экземпляр tempPickupEffect):

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.name == "Player_Ship")
    {
        AudioSource.PlayClipAtPoint(receiveSound, Camera.main.transform.position, 0.5f);

        GameObject tempPickupEffect = Instantiate(pickupEffect, transform.position, transform.rotation) as GameObject;
        tempPickupEffect.GetComponent<ParticleSystem>().Play();
        Destroy(tempPickupEffect, 3f);

        heal = true;
        Level1.playerHealth += healAmount;

        Destroy(gameObject);
    }
}

Под моим вражеским сценарием у меня есть метод spawnHealthUp ()вызывается, когда здоровье врага находится на уровне или ниже нуля.Это метод:

private void spawnHealthUp()
{
    chance = Random.value;
    if (chance <= healthSpawnChance)
    {
        GameObject copyHealthUp = Instantiate(healthUp, transform.position, Quaternion.identity) as GameObject;
        copyHealthUp.GetComponent<Rigidbody2D>().velocity = new Vector2(-healthSpeed, 0f);
    }
}

Заранее благодарим вас за понимание, которое может предложить каждый.

1 Ответ

0 голосов
/ 16 сентября 2018

В вашем случае может происходить несколько вещей, но я бы сказал, что либо ваша переменная "pickupEffect" как-то становится недействительной, либо это происходит из-за вызова:

tempPickupEffect.GetComponent<ParticleSystem>().Play();

Я разбью оба случая более подробно ниже.

Во-первых, вы можете добавить проверку, чтобы убедиться, что для переменной «pickupEffect» задано значение NULL или какой-то скрипт уничтожает этот GameObject / prefab (вызывая для него Destroy ()). Добавьте эту проверку прямо перед вызовом Instantiate(pickupEffect, ...) внутри вашего OnTriggerEnter2D(...) метода. Это можно сделать, сравнив pickupEffect == null (оператор == переопределен и проверит, был ли уничтожен GameObject / prefab, как указано в в этом ответе ).

Если объект разрушается, простой способ определить , где он уничтожается , сделать следующее: создать небольшой скрипт, содержащий функцию OnDisable(), и добавить вызов Debug.Log() с любым текстом на нем. Вызов Debug.Log() зарегистрирует ваш текст, а также добавит трассировку стека к сообщению журнала, которое вы можете использовать, чтобы проверить, где был сделан вызов функции Destroy() (и, таким образом, обнаружить где ваш GameObject уничтожается).

// This script should be added to the "pickupEffect" gameobject
void OnDisable()
{
    Debug.Log("Object destroyed!");
}

Когда объект уничтожается, генерируется вывод, подобный следующему:

Object destroyed!
UnityEngine.Debug:Log(Object)
MyObjectBeingDeleted:OnDisable() (at
Assets/MyObjectBeingDeleted.cs:10) UnityEngine.Object:Destroy(Object)
MyDestroyerObject:Update() (at Assets/MyDestroyerObject.cs:11)

Приведенная выше трассировка стека говорит мне, что метод Destroy() был вызван в строке 11 сценария MyDestroyerObject.cs .


С другой стороны, проблема на самом деле может быть в этой части вашего кода:

tempPickupEffect.GetComponent<ParticleSystem>().Play();
Destroy(tempPickupEffect, 3f);

Здесь вы даете команду ParticleSystem на игру, но сразу после того, как вы отправите эту команду, вы уничтожаете GameObject, который содержит эту систему Particle System. На самом деле это плохая практика (и может привести к исключениям, которые трудно отладить). Я рекомендую вам создать сценарий с методом Update(), который проверяет, завершила ли система Particle свое выполнение, и уничтожает объект после того, как это выполнение завершилось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...