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

Unity推箱子类游戏多可推动物体移动异常问题求助

问题分析与解决方案

问题描述

  • 已实现同时推动3个可推动物体,但队列末尾的可推动物体碰到障碍物时,第一个物体会与下一个物体重叠。
  • 需求:只要队列最后一个可推动物体不会触碰障碍物,无论后方有多少可推动物体,都能推动任意数量的可推动物体。

现有代码问题

现有代码硬编码处理最多3个可推动物体的场景,逻辑嵌套复杂,且存在边检测边移动的错误逻辑——当检测到末端障碍时,前面的物体已经被移动,直接导致重叠。正确逻辑应该是先完整验证整个推动链的路径是否畅通,再一次性移动所有物体。

修改后的代码

// 尝试推动当前物体及后续的可推动物体链
public bool PushMove(Vector2 direction)
{
    // 先检测整个推动链是否具备移动条件
    List<Transform> pushChain = GetPushChain(transform.position, direction);
    if (pushChain == null)
    {
        return false;
    }

    // 一次性移动链条上的所有物体
    foreach (var obj in pushChain)
    {
        obj.Translate(direction);
    }
    return true;
}

// 获取当前方向上的完整可推动物体链,若末端存在障碍物则返回null
private List<Transform> GetPushChain(Vector3 startPos, Vector2 direction)
{
    List<Transform> chain = new List<Transform>();
    Vector2 currentPos = new Vector2(startPos.x, startPos.y);

    while (true)
    {
        currentPos += direction;

        // 检查当前位置是否是障碍物
        if (IsObstacle(currentPos))
        {
            return null; // 末端遇障,无法推动
        }

        // 检查当前位置是否存在可推动物体
        Transform pushable = GetPushableAtPosition(currentPos);
        if (pushable == null)
        {
            break; // 无更多可推动物体,链条检测完成
        }

        // 防止循环检测同一物体
        if (chain.Contains(pushable))
        {
            return null;
        }

        chain.Add(pushable);
    }

    return chain;
}

// 检查指定位置是否存在障碍物
private bool IsObstacle(Vector2 pos)
{
    foreach (var obstacle in NotMovableObj)
    {
        if (obstacle.transform.position.x == pos.x && obstacle.transform.position.y == pos.y)
        {
            return true;
        }
    }
    return false;
}

// 获取指定位置的可推动物体
private Transform GetPushableAtPosition(Vector2 pos)
{
    foreach (var pushable in MovableObj)
    {
        if (pushable.transform.position.x == pos.x && pushable.transform.position.y == pos.y)
        {
            return pushable.transform;
        }
    }
    return null;
}

代码说明

  • GetPushChain方法:从起始位置出发,沿推动方向循环检测所有可推动物体,直到碰到空位置或障碍物。若遇障则返回null,表示无法推动;否则返回完整的可推动物体链。
  • PushMove方法:先通过GetPushChain确认整个链条可移动,再一次性完成所有物体的移动,彻底避免边移边检测导致的重叠问题。
  • 拆分辅助方法:将障碍物检测、可推动物体检测拆分为独立方法,简化主逻辑,提升代码可读性。
  • 支持任意数量:不再限制可推动物体的数量,无论链条长度如何,只要末端无障碍物就能正常推动。

关键改进点

  1. 先检测后移动:确保整个推动路径完全畅通后再执行移动,从根源解决物体重叠问题。
  2. 动态生成推动链:通过循环自动识别所有可推动物体,适配任意长度的推动队列。
  3. 逻辑解耦:拆分重复检测逻辑,降低代码复杂度,便于后续维护和扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:15:39