如何让玩家移动不受旋转与重力影响且保留碰撞检测?
嘿,我完全懂你这种卡壳的感觉——折腾了一天还没搞定,换谁都烦。你遇到的核心问题就是全局空间和局部空间的移动不匹配,加上之前的两种方法要么绕远路效率低,要么直接跳过物理引擎导致穿墙。
先帮你把坑踩掉:
- 改标签调速度:这种方式纯纯绕远路,不仅效率低,还容易因为频繁修改状态触发不必要的逻辑,完全没必要。
- 直接改
transform.position:这相当于绕过了Unity的物理引擎,碰撞检测自然失效,穿墙是必然结果。
正确解决方案:基于局部坐标系+物理引擎驱动移动
核心思路就是:让移动方向完全贴合玩家自身的朝向(局部空间),同时通过Rigidbody2D执行移动,让物理引擎全程处理碰撞、重力等效果。这里给你两种常用的实现方式:
方法一:用AddForce(物理感更强)
这种方式是给刚体施加持续力,和重力、碰撞力自然叠加,手感更贴近真实物理效果:
public float moveForce = 20f; private Rigidbody2D _rb; void Start() { // 提前获取组件,避免每帧调用GetComponent浪费性能 _rb = GetComponent<Rigidbody2D>(); } void FixedUpdate() { // 水平输入值(-1到1) float horizontalInput = Input.GetAxis("Horizontal"); // 基于玩家自身的右侧方向构建移动向量 // transform.right 永远指向玩家当前朝向的右侧,和旋转角度无关 Vector2 localMoveDir = horizontalInput * (Vector2)transform.right; // 施加持续力,Force模式适合持续移动的场景 _rb.AddForce(localMoveDir * moveForce, ForceMode2D.Force); }
方法二:直接控制Velocity(精准度更高)
如果需要固定移动速度,不想让力叠加导致速度越来越快,可以直接修改速度,但要注意保留重力等其他力的影响:
public float moveSpeed = 5f; private Rigidbody2D _rb; void Start() { _rb = GetComponent<Rigidbody2D>(); } void FixedUpdate() { float horizontalInput = Input.GetAxis("Horizontal"); // 计算玩家想要的局部移动速度 Vector2 desiredLocalVelocity = horizontalInput * (Vector2)transform.right * moveSpeed; // 保留垂直于移动方向的速度分量(比如重力带来的下落/侧移速度) // 这样既保证移动方向正确,又不会抵消重力的效果 Vector2 nonInputVelocity = _rb.velocity - Vector2.Dot(_rb.velocity, (Vector2)transform.right) * (Vector2)transform.right; // 最终速度 = 玩家输入的移动速度 + 其他力带来的速度 _rb.velocity = desiredLocalVelocity + nonInputVelocity; }
关键细节
transform.right是玩家对象的局部右侧方向,不管你把玩家旋转多少度、重力改成左/上/下,这个方向始终对应玩家自身的“右”,所以输入的右键会精准触发玩家向自己右侧移动,完美解决你之前的方向错位问题。
另外记得:所有和Rigidbody2D相关的逻辑都要放在FixedUpdate里,因为它和物理引擎的更新帧同步,移动会更平滑稳定。
内容的提问来源于stack exchange,提问作者Rioni




