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

寻求Unity中基于坐标查找特定GameObject的高效优化方案

高效通过X/Y坐标查找Unity中的SampleScript组件

核心问题分析

GameObject.Find()是全局遍历查找,每次调用都会扫描场景内所有对象,在循环中反复调用会严重拖慢性能。最优方案是提前缓存所有SampleScript实例,后续通过坐标直接索引,将多次查找的O(n)成本转化为初始化时的一次性O(n)成本,后续查询均为O(1)。


方案1:二维数组缓存(适合坐标连续且范围固定的场景)

利用你已定义的maximumX和maximumY,创建对应尺寸的二维数组,初始化时将所有SampleScript按坐标存入数组,后续直接通过坐标索引。

优化后代码示例

[SerializeField] private int maximumX;
[SerializeField] private int maximumY;
private SampleScript[,] _sampleGrid;

void Awake()
{
    // 初始化二维数组
    _sampleGrid = new SampleScript[maximumX, maximumY];
    
    // 一次性获取场景中所有SampleScript组件
    var allSamples = FindObjectsOfType<SampleScript>();
    
    foreach (var sample in allSamples)
    {
        // 校验坐标合法性,避免数组越界
        if (sample.xCoordinate >= 0 && sample.xCoordinate < maximumX && 
            sample.yCoordinate >= 0 && sample.yCoordinate < maximumY)
        {
            _sampleGrid[sample.xCoordinate, sample.yCoordinate] = sample;
        }
        else
        {
            Debug.LogWarning($"SampleScript at ({sample.xCoordinate}, {sample.yCoordinate}) exceeds grid bounds");
        }
    }
}

public void Example(int x, int y)
{
    // 边界检查
    if (x < 0 || x >= maximumX || y < 0 || y >= maximumY)
    {
        Debug.LogError($"Object ({x}, {y}) is out of grid bounds");
        return;
    }

    var targetExample = _sampleGrid[x, y];
    if (targetExample == null)
    {
        Debug.LogError($"No SampleScript found at ({x}, {y})");
        return;
    }

    Debug.Log($"{targetExample} X value: {targetExample.xCoordinate}");
    Debug.Log($"{targetExample} Y value: {targetExample.yCoordinate}");
    Debug.Log($"{targetExample} isValid: {targetExample.isValid}");
}

方案2:字典缓存(适合坐标不连续或动态变化的场景)

用坐标元组作为键,SampleScript实例作为值存入字典,支持非连续坐标,且能灵活处理对象的动态创建/销毁。

优化后代码示例

[SerializeField] private int maximumX;
[SerializeField] private int maximumY;
private Dictionary<(int x, int y), SampleScript> _sampleDict;

void Awake()
{
    _sampleDict = new Dictionary<(int x, int y), SampleScript>();
    var allSamples = FindObjectsOfType<SampleScript>();
    
    foreach (var sample in allSamples)
    {
        var key = (sample.xCoordinate, sample.yCoordinate);
        if (_sampleDict.ContainsKey(key))
        {
            Debug.LogWarning($"Duplicate SampleScript detected at ({sample.xCoordinate}, {sample.yCoordinate})");
            continue;
        }
        _sampleDict[key] = sample;
    }
}

// 若需支持动态对象,添加注册/注销方法
public void RegisterSample(SampleScript sample)
{
    var key = (sample.xCoordinate, sample.yCoordinate);
    _sampleDict[key] = sample;
}

public void UnregisterSample(SampleScript sample)
{
    var key = (sample.xCoordinate, sample.yCoordinate);
    if (_sampleDict.TryGetValue(key, out var existing) && existing == sample)
    {
        _sampleDict.Remove(key);
    }
}

public void Example(int x, int y)
{
    var key = (x, y);
    if (!_sampleDict.TryGetValue(key, out var targetExample))
    {
        Debug.LogError($"No SampleScript found at ({x}, {y})");
        return;
    }

    Debug.Log($"{targetExample} X value: {targetExample.xCoordinate}");
    Debug.Log($"{targetExample} Y value: {targetExample.yCoordinate}");
    Debug.Log($"{targetExample} isValid: {targetExample.isValid}");
}

动态对象适配

在SampleScript中添加生命周期方法,自动维护字典缓存:

public class SampleScript : MonoBehaviour
{
    public int xCoordinate;
    public int yCoordinate;
    public bool isValid;

    private void OnEnable()
    {
        // 假设GridManager是全局单例类
        GridManager.Instance.RegisterSample(this);
    }

    private void OnDisable()
    {
        GridManager.Instance.UnregisterSample(this);
    }
}

方案选择建议

  • 若坐标范围固定且连续,优先用二维数组,查询速度略快于字典,内存占用更紧凑。
  • 若坐标不连续或对象会动态创建/销毁,选择字典方案,灵活性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:35:31