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
相关产品推荐
相关产品推荐

