什么是最有效的方法来接近目标?

3
什么是最有效且费用较低的方法来从这两种方法中获得最接近的目标 ?
使用LINQ。
GameObject FindClosestTarget(string trgt) 
{
    GameObject[] closestGameObject = GameObject.FindGameObjectsWithTag(trgt)
                      .OrderBy(go => Vector3.Distance(go.transform.position, transform.position)
                      .FirstOrDefault();
         return closestGameObject ;
}

或者这样

 GameObject FindClosestTarget(string trgt) 
     {
         GameObject[] gos= GameObject.FindGameObjectsWithTag(trgt);

         GameObject closest=null;
         float distance = Mathf.Infinity;
         Vector3 position = transform.position;
         foreach (GameObject go in gos) {
             Vector3 diff = go.transform.position - position;
             float curDistance = diff.sqrMagnitude;

             if (curDistance < distance) {
                 closest = go;
                 distance = curDistance;
             }
         }

         return closest;
     }

3
您可以使用Debug.log和Time.deltaTime进行检查,哪个更快。 - Rasa Mohamed
哪一个是最快的?CPU 使用率较低的那个? - Sajitha Rathnayake
如果你有成千上万的对象,并且每一帧都想找到最接近(n个最接近)的对象,那么实现四叉树/八叉树是一个好主意。但是如果你没有那么多的对象,那就无所谓了。 - Adrian Krupa
我是Unity开发的新手。比较代码的最佳方法是什么?如何在Unity中查看FPS? - Sajitha Rathnayake
1
OrderBy的速度要慢得多(是的,慢得多,但你不会感觉到,因为今天的处理器非常快!)。如果您担心性能问题,请将linq版本保留在注释中,但使用第二个版本,这样您就不会忘记正在发生什么。 - M.kazem Akhgary
显示剩余2条评论
3个回答

10

第一个示例使用Vector3.Distance,需要进行相当昂贵的Sqrt操作,而第二个示例使用我更喜欢抛弃的简单LINQ形式的代码。

以下是Unity Scripting API文档中sqrMagnitude的摘录:

向量v的大小可以计算为Mathf.Sqrt(Vector3.Dot(v, v))。然而,Sqrt计算非常复杂,执行时间比正常算术运算要长。计算平方大小而不是使用大小属性要快得多-计算基本相同,只是没有缓慢的Sqrt调用。如果您仅使用大小比较距离,那么您也可以将平方大小与距离的平方进行比较,因为比较将给出相同的结果。

因此,您的场景基本上就是他们创建sqrMagnitude属性的原因...因为Sqrt是一项昂贵的操作,如果您只想知道距离顺序而不需要稍后使用实际距离,则不需要它。

就我个人而言,我更喜欢这作为第三个选项:

GameObject FindClosestTarget(string trgt)
{
    Vector3 position = transform.position;
    return GameObject.FindGameObjectsWithTag(trgt)
        .OrderBy(o => (o.transform.position - position).sqrMagnitude)
        .FirstOrDefault();
}

最好的两个世界... LINQ 的简单性(和相当高效的实现)与没有多余的 Sqrt 操作来拖慢你的速度。

但是,当你对代码的真实性能有疑问时,你应该仔细地对每种方法进行分析,看看哪种方法实际上执行得更好。有时候优化器会给你一个曲线球,将可怕的 C# 代码转换成相当有效的输出。

顺便说一句,如果你想限制你的范围到特定的最大距离,那么可以将该距离平方并将其与 sqrMaginitude 进行比较,以避免恶意的 Sqrt


3

编辑: 正如Corey所建议的,这个答案没有考虑到下面的方法使用了sqrt,这确实使它变慢了。

我不认为差异很关键,但就原始速度而言,我认为第二种方法会稍微快一些,因为你不是对整个列表进行排序(最优时间复杂度为O(n*log(n))),而只是获取与距离最近的那个(O(n))。

然而,如果这不是程序中真正关键的点,我总是会选择第一个...它只是更好看。


在这种情况下,OrderBy/Sort是微不足道的。最昂贵的是距离的计算,因此差异可能非常微小。 - David
@David 我不熟悉Unity,所以我想你说得对。然而,由于两种情况下都必须计算距离,唯一重要的是gis设置的速度(他要求的)。此外,当您有大量目标要比较时,sort()将变得越来越明显。正如我提到的,我仍然同意您使用LinQ。 - xXliolauXx
2
你不觉得避免使用Sqrt会稍微加快速度吗?性能并不完全取决于复杂度的顺序 :P - Corey

1
如果你有太多的游戏物体,想要找到最接近的一个物体,而不是检查所有的物体并进行比较,那么你可以使用触发器。将一个球形碰撞体附加到你的玩家身上,并增大它的大小,直到它与其他任何游戏物体相碰撞。
不要认为使用碰撞体总是更糟糕的。试一试,我认为这会是一个更好的方法。(但是如我所说,如果你有太多的物体需要检查)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接