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

Unity运行时立方体自动匹配最近未占用目标点并停靠实现方案咨询

Unity动态生成立方体自动匹配目标点实现方案

核心实现思路

采用全局分配器+事件触发的分配逻辑,完全避免实时轮询的无效计算,同时通过全局统一调度解决多个立方体争抢同一个目标点的冲突问题,符合动态生成的使用场景。

  • 目标点做独立状态标记,区分空闲/占用状态,状态变更时触发重新分配
  • 仅在新立方体生成、新目标点生成、已占用目标点释放三个节点执行一次分配逻辑,无多余计算
  • 全局维护未分配立方体、空闲目标点两个动态列表,统一做距离匹配,避免单个立方体自行查找导致的分配冲突

核心代码示例

目标点状态脚本TargetPoint.cs

public class TargetPoint : MonoBehaviour
{
    public bool isOccupied = false;
    public Transform boundCube;

    // 立方体抵达后调用标记占用
    public void MarkOccupied(Transform cube)
    {
        isOccupied = true;
        boundCube = cube;
    }

    // 立方体离开后调用释放点位
    public void Release()
    {
        isOccupied = false;
        boundCube = null;
        // 释放后触发分配器重新分配
        CubeTargetAllocator.Instance.TryAssignTargets();
    }
}

全局分配器单例CubeTargetAllocator.cs

public class CubeTargetAllocator : MonoBehaviour
{
    public static CubeTargetAllocator Instance;

    // 动态维护的未分配立方体、空闲目标点列表
    public List<Transform> unassignedCubes = new List<Transform>();
    public List<TargetPoint> availableTargets = new List<TargetPoint>();

    private void Awake()
    {
        if (Instance == null) Instance = this;
        else Destroy(gameObject);
    }

    // 新生成立方体时调用,加入未分配队列
    public void AddNewCube(Transform newCube)
    {
        unassignedCubes.Add(newCube);
        TryAssignTargets();
    }

    // 新生成目标点时调用,加入空闲队列
    public void AddNewTarget(TargetPoint newTarget)
    {
        if(!newTarget.isOccupied) availableTargets.Add(newTarget);
        TryAssignTargets();
    }

    // 核心分配逻辑
    public void TryAssignTargets()
    {
        // 无待分配对象/无空闲点位直接返回
        if (unassignedCubes.Count == 0 || availableTargets.Count == 0) return;

        // 倒序遍历避免移除元素时索引错位
        for (int i = unassignedCubes.Count - 1; i >= 0; i--)
        {
            Transform cube = unassignedCubes[i];
            float minDistance = float.MaxValue;
            TargetPoint nearestTarget = null;

            // 匹配当前立方体最近的空闲点位
            foreach (var target in availableTargets)
            {
                // 数量级大时可以换成sqrMagnitude比较,省去开方开销
                float distance = Vector3.Distance(cube.position, target.transform.position);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestTarget = target;
                }
            }

            if (nearestTarget != null)
            {
                // 绑定目标点启动移动
                cube.GetComponent<CubeMove>().SetTarget(nearestTarget);
                // 移除已分配的点位和立方体
                availableTargets.Remove(nearestTarget);
                unassignedCubes.RemoveAt(i);
            }
        }
    }
}

立方体移动脚本CubeMove.cs

public class CubeMove : MonoBehaviour
{
    private TargetPoint currentTarget;
    public float moveSpeed = 2f;
    private float stopThreshold = 0.05f;

    public void SetTarget(TargetPoint target)
    {
        currentTarget = target;
    }

    private void Update()
    {
        if (currentTarget == null) return;

        // 原有MoveTowards移动逻辑保留
        transform.position = Vector3.MoveTowards(transform.position, currentTarget.transform.position, moveSpeed * Time.deltaTime);

        // 抵达目标点后标记占用
        if (Vector3.Distance(transform.position, currentTarget.transform.position) < stopThreshold)
        {
            currentTarget.MarkOccupied(transform);
            currentTarget = null;
        }
    }
}

使用说明

  • 动态生成立方体后调用CubeTargetAllocator.Instance.AddNewCube(新立方体Transform)即可触发自动分配
  • 动态生成目标点后调用CubeTargetAllocator.Instance.AddNewTarget(新目标点TargetPoint组件)即可触发自动分配
  • 不需要在编辑器内做任何拖拽赋值,完全适配运行时动态生成的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 04:57:03