You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GameObject数组中找到离指定对象最近的两个GameObject(排除自身)

问题描述

我正在开发一款游戏,需要从同一个GameObject列表中找到离某一指定GameObject最近的2个GameObject,要求返回结果不超过2个,且不能返回被检测的GameObject本身。

输入输出

  • 期望输入:
GameObject[] objects, GameObject currentObject
  • 期望输出:
GameObject[] closestObjects, GameObject currentObject

尝试的代码

我尝试了以下代码(其中paths对应objects,pathToTest对应currentObject,bestTargets对应closestObjects):

GameObject [ ] GetClosestPaths ( GameObject [ ] paths, GameObject pathToTest )
{
    GameObject[] bestTargets = new GameObject[2];
    float closestDistanceSqr = Mathf.Infinity;
    Vector3 currentPosition = pathToTest.transform.position;
    Transform[] pathTransforms = new Transform[paths.Length];

    for ( int i = 0; i < paths.Length; i++ )
    {
        pathTransforms [ i ] = paths [ i ].transform;
    }

    for ( int i = 0; i < pathTransforms.Length; i++ )
    {
        if ( pathTransforms [ i ].position != currentPosition && paths [ i ] != pathToTest )
        {
            Transform potentialTarget = pathTransforms[i];
            Vector3 directionToTarget = potentialTarget.position - currentPosition;
            float dSqrToTarget = directionToTarget.sqrMagnitude;
            if ( dSqrToTarget < closestDistanceSqr )
            {
                if ( bestTargets [ 0 ] == null )
                {
                    bestTargets [ 0 ] = paths [ i ];
                }
                closestDistanceSqr = dSqrToTarget;
                if ( paths [ i ].transform.position != bestTargets [ 0 ].transform.position )
                {
                    bestTargets [ 0 ] = paths [ i ];
                }
                else
                {
                    bestTargets [ 1 ] = paths [ i ];
                }
            }
        }
    }

    return bestTargets;
}

这段代码来自Stackoverflow,但完全无法正常工作,项目因此面临搁置,希望得到帮助。

解决方案

问题分析

原代码的核心问题在于逻辑混乱:

  • 仅维护一个closestDistanceSqr变量,无法同时追踪第一近和第二近的距离
  • 替换目标的逻辑错误,会覆盖已找到的最近目标,且无法正确填充第二近的对象
  • 用position != currentPosition判断是否为自身不可靠,不同对象可能位置相同,应直接用对象引用比较paths[i] != pathToTest

修正后的代码

以下是逻辑清晰、满足需求的实现:

GameObject[] GetClosestObjects(GameObject[] objects, GameObject currentObject)
{
    // 存储候选对象与对应平方距离(避免开方,提升性能)
    List<(GameObject obj, float distanceSqr)> candidates = new List<(GameObject, float)>();
    Vector3 currentPos = currentObject.transform.position;

    foreach (GameObject obj in objects)
    {
        // 直接排除自身
        if (obj == currentObject)
            continue;

        float distanceSqr = (obj.transform.position - currentPos).sqrMagnitude;
        candidates.Add((obj, distanceSqr));
    }

    // 按距离升序排序,取前2个
    var sortedCandidates = candidates.OrderBy(c => c.distanceSqr).Take(2).ToList();

    // 生成结果数组,不足2个时剩余位置为null
    GameObject[] result = new GameObject[2];
    for (int i = 0; i < sortedCandidates.Count; i++)
    {
        result[i] = sortedCandidates[i].obj;
    }

    return result;
}

代码说明

  • 用List存储有效候选对象及其平方距离,避免频繁数组操作
  • 以对象引用obj == currentObject排除自身,比位置判断更可靠
  • 借助Linq的OrderBy和Take快速筛选前2近对象,逻辑直观
  • 结果数组不足2个时,剩余位置保留为null,符合“返回结果不超过2个”的要求

性能优化版本

如果对象列表规模很大,Linq排序效率有限,可以手动维护前2近的对象,仅遍历一次列表:

GameObject[] GetClosestObjectsOptimized(GameObject[] objects, GameObject currentObject)
{
    GameObject closest1 = null;
    GameObject closest2 = null;
    float distSqr1 = float.MaxValue;
    float distSqr2 = float.MaxValue;
    Vector3 currentPos = currentObject.transform.position;

    foreach (GameObject obj in objects)
    {
        if (obj == currentObject)
            continue;

        float distSqr = (obj.transform.position - currentPos).sqrMagnitude;

        // 更新前两名对象
        if (distSqr < distSqr1)
        {
            closest2 = closest1;
            distSqr2 = distSqr1;
            closest1 = obj;
            distSqr1 = distSqr;
        }
        else if (distSqr < distSqr2)
        {
            closest2 = obj;
            distSqr2 = distSqr;
        }
    }

    return new GameObject[] { closest1, closest2 };
}

该方法时间复杂度为O(n),适合处理大量对象的场景。


内容的提问来源于stack exchange,提问作者Tauras129

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:25:39