You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让玩家移动不受旋转与重力影响且保留碰撞检测?

嘿,我完全懂你这种卡壳的感觉——折腾了一天还没搞定,换谁都烦。你遇到的核心问题就是全局空间和局部空间的移动不匹配,加上之前的两种方法要么绕远路效率低,要么直接跳过物理引擎导致穿墙。

先帮你把坑踩掉:

  • 改标签调速度:这种方式纯纯绕远路,不仅效率低,还容易因为频繁修改状态触发不必要的逻辑,完全没必要。
  • 直接改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

火山引擎 最新活动