我有一个 Health 游戏对象,有机会在摧毁敌人时进行实例化 . 大多数时候,它会治疗玩家,播放声音效果等等 . 换句话说,它的行为方式应该如此 . 但是,有时候(可能是10次中的1次)当遇到实例化的对象时,它会播放声音效果,但不会治愈播放器,也不会被摧毁 . 随之而来的错误是:
MissingReferenceException:“GameObject”类型的对象已被破坏,但您仍在尝试访问它 . 您的脚本应该检查它是否为null或者您不应该销毁该对象 . UnityEngine.Object.Internal_InstantiateSingle(UnityEngine.Object数据,Vector3 pos,Quaternion rot)UnityEngine.Object.Instantiate(UnityEngine.Object original,Vector3 position,Quaternion rotation)(在C:/ buildslave / unity / build / Runtime / Export / UnityEngineObject .bindings.cs:211)UnityEngine.Object.Instantiate [GameObject](UnityEngine.GameObject original,Vector3 position,Quaternion rotation)(at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.bindings.cs:285) Heart.OnTriggerEnter2D(UnityEngine.Collider2D碰撞)(在Assets / Scripts / Heart.cs:36)
我一直试图弄清楚发生了什么,我似乎无法确定问题 . 在错误指向的 Health 状况对象下(错误实际上指向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 回答
在你的情况下可能会发生很多事情,但我会说你的“pickupEffect”变量以某种方式失效,或者这是因为调用:
tempPickupEffect.GetComponent<ParticleSystem>().Play();
我将在下面详细介绍这两种情况 .
首先,您可以添加一个检查以查看"pickupEffect"变量是否设置为null或某些脚本正在销毁该GameObject / prefab(通过调用它上面的Destroy()) . 在
OnTriggerEnter2D(...)
方法中调用Instantiate(pickupEffect, ...)
之前添加此检查 . 这可以通过比较pickupEffect == null
来完成(==
运算符被覆盖,并将根据this answer中的sugested检查GameObject / prefab是否已被销毁) .如果对象被破坏,通过执行以下操作来检测 where it is being destroyed 的简单方法是:创建一个包含
OnDisable()
函数的小脚本,并添加一个带有任何文本的Debug.Log()
调用 .Debug.Log()
调用将记录您的文本,并且还会在日志消息中添加 stack trace ,您可以使用该消息来验证对Destroy()
函数的调用位置(从而发现您的GameObject被销毁的位置) .当te对象被破坏时,将生成类似于以下内容的输出:
上面的堆栈跟踪告诉我
Destroy()
方法已在 MyDestroyerObject.cs 脚本的 line 11 上调用 .另一方面,问题实际上可能出现在代码的这一部分:
在这里您要命令粒子系统播放,但是在您发出该命令之后,您正在销毁包含该粒子系统的GameObject . 这实际上是一种不好的做法(最终可能会导致难以调试的异常) . 我建议您使用
Update()
方法创建一个脚本,该方法检查粒子系统是否已结束其执行,并在执行结束后销毁该对象 .