我目前正在为我的太空射击项目中的敌人开发基本的AI。
在我的EnemyAI脚本中,我有一个实例化敌人时设置的public Transform target
。在Update循环中,我正在查看目标,然后使用transform.towards
移动,一切正常。问题是target
可能会死亡,因此我需要在执行所有操作之前检查它是否不为null。问题是:显然做一个简单的if(target == null)
确实是很糟糕的性能,我需要在Update中进行。在没有性能问题的情况下实现这一目标的最佳方法应该是什么(假设我一次要500个敌人)。我是否仍应在每个X帧中执行此操作,将目标的位置缓存到下一次检查,然后移向该缓存的结果?这可能有效,但如果两次检查之间的时间过长,则会引入抖动。
我找不到任何“简单”的方法,但我希望有一种方法,它看起来很简单,并且会引起很多麻烦:/
答案 0 :(得分:2)
答案 1 :(得分:0)
我检查并测试了它,是的,您可以使用回调函数来执行此操作,该回调函数将注册到目标的OnDestroy
方法中。您的Player script
应该访问目标脚本并委托这样的方法:
public GameObject target;
private TargetScript myTargetScript;
void Start () {
myTargetScript = target.GetComponent<TargetScript>();
myTargetScript.OnDestroyEvnt += OnDestroyListener;
}
private void OnDestroyListener(MonoBehaviour instance)
{
Debug.Log("Callback is called");
}
Target script
也应该像这样:
public event OnDestroyDelegate OnDestroyEvnt;
public delegate void OnDestroyDelegate(MonoBehaviour instance);
void Start () {
StartCoroutine(DestroyCoroutine());
}
private void OnDestroy()
{
if (this.OnDestroyEvnt != null)
{
this.OnDestroyEvnt(this);
}
}
IEnumerator DestroyCoroutine()
{
yield return new WaitForSeconds(5);
Destroy(gameObject);
}
5秒后,我用协程破坏了该物体。这实际上与您的情况无关。我采用了here中的这段代码。
答案 2 :(得分:0)
注意 UnityEngine.Object 子项的空检查不是标准的 C# 空检查。 Jetbrains 提供的与 Rider IDE 和分析工具相关的 description 深入了解了细节。基本思想是 C# 脚本将 null 检查交给底层 C++ 引擎结构。
我不需要它,但我看到其他人的代码保留了一个简单的 UnityEngine.Object 引用列表。它们在创建对象时将对该对象的引用添加到列表中。然后将其从销毁列表中删除。 Update() 然后可以在列表中使用更快的测试。在速度至关重要的地方,您只需测试列表而不是对象。当然,也可以使用列表以外的方法。
答案 3 :(得分:-2)
您可以在逻辑上避免它,创建一个仅在分配目标时才运行的协程,如果目标为null,则结束协程,该协程应具有一个...
yield return new WaitForEndOfFrame();
那样,它将像一种LateUpdate
一样。
然后检查每一帧...
while (target != null)
您仍将每个帧都检查为空,但只检查一次target = null
。