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

Unity 2D中使用GetKey与transform.position控制对象无法移动问题求助

搞定你的PacMan移动问题!

刚看完你的代码,几个关键问题导致角色无法移动,咱们一步步捋清楚:

1. valid函数逻辑完全搞反了

这是最核心的问题!你现在的valid函数是在判断“射线只碰到自己的碰撞体”才允许移动,但实际咱们需要的是“目标方向没有障碍物”。

看你原来的代码:

bool valid(Vector2 dir) { 
    Vector2 pos = transform.position; 
    RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos); 
    return (hit.collider == GetComponent<Collider2D>()); 
}

当你想向上移动时,射线从pos+up射向当前位置,如果上方有墙,射线会先碰到墙的碰撞体,返回的hit.collider就不是PacMan自己的,导致valid返回false,自然没法移动。

修正后的valid函数(两种方案选一种就行):

  • 方案一:用OverlapPoint检测下一步位置是否有障碍物
bool valid(Vector2 dir) {
    Collider2D myCol = GetComponent<Collider2D>();
    // 计算要移动到的下一个位置
    Vector2 nextPos = (Vector2)transform.position + dir;
    // 检测该位置是否有其他碰撞体(排除自己的层)
    Collider2D obstacle = Physics2D.OverlapPoint(nextPos, ~myCol.gameObject.layer);
    // 没障碍物就返回true
    return obstacle == null;
}
  • 方案二:调整Linecast的逻辑
bool valid(Vector2 dir) {
    Vector2 pos = transform.position;
    // 从当前位置向目标方向发射射线,长度为1格
    RaycastHit2D hit = Physics2D.Linecast(pos, pos + dir);
    // 要么没碰到任何东西,要么只碰到自己(避免检测到自身碰撞体)
    return hit.collider == null || hit.collider == GetComponent<Collider2D>();
}

2. 输入检测的小优化

你在FixedUpdate里用Input.GetKey,虽然能工作,但按住方向键时会反复触发判断。换成Input.GetKeyDown更符合吃豆人“按一次走一格”的操作逻辑:

if (Vector2.Distance(transform.position, dest) < 0.01f) { // 替换原来的直接相等判断
    if (Input.GetKeyDown(KeyCode.UpArrow) && valid(Vector2.up))
        dest = (Vector2)transform.position + Vector2.up;
    if (Input.GetKeyDown(KeyCode.RightArrow) && valid(Vector2.right))
        dest = (Vector2)transform.position + Vector2.right;
    if (Input.GetKeyDown(KeyCode.DownArrow) && valid(-Vector2.up))
        dest = (Vector2)transform.position - Vector2.up;
    if (Input.GetKeyDown(KeyCode.LeftArrow) && valid(-Vector2.right))
        dest = (Vector2)transform.position - Vector2.right;
}

3. 编辑器里的必查设置

别光改代码,这些设置错了也会导致移动失败:

  • 确认PacMan的Rigidbody2D是Dynamic类型,Gravity Scale设为0(毕竟是平面移动,不需要重力)。
  • 确认PacMan的Collider2D(比如CircleCollider2D)没勾选Is Trigger,不然射线检测会跳过它。
  • 地图里的墙必须有Collider2D组件,而且和PacMan的碰撞层要能互相检测(在Physics2D设置里确认层碰撞矩阵)。

4. 浮点数精度坑

原来的(Vector2)transform.position == dest直接比较浮点数,很容易因为微小的精度误差导致永远判定“没到达目标点”,换成判断距离的方式就稳妥了:

if (Vector2.Distance(transform.position, dest) < 0.01f) {
    // 这里放输入检测逻辑
}

把这些改完,你的PacMan应该就能正常动起来啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:27:35