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

Unity中基于加速度的滑冰风格移动系统问题排查

冰面滑冰移动系统问题排查与修复

问题原因拆解

1. 按键方向与本地坐标轴不匹配

  • 速度角度基准错位:vangle通过Math.Atan2(v.y, v.x)计算,该方法以世界X轴正方向为0度;而玩家朝向fangle以世界Z轴正方向为0度,两者基准相差90度,导致加速度向量与速度向量方向错位。
  • 横向角度偏移错误:构建横向加速度时使用fangle+90,不符合Unity顺时针旋转的坐标系逻辑,导致左右方向输入与实际移动方向不符。

2. 速度方向切换不流畅

  • 减速逻辑错误:直接减小速度大小而非对速度向量施加反向摩擦力,导致速度方向被锁死在原有方向,只有当速度接近0时,新加速度才能主导方向。
  • 速度维护方式不合理:将速度拆分为大小和角度分别维护,无法实现平滑的方向过渡,不符合冰面滑行的物理逻辑。

修复后的代码

改为直接维护世界空间速度向量,采用物理化的移动逻辑,彻底解决方向与流畅度问题:

using UnityEngine;

public class IceSkaterMovement : MonoBehaviour
{
    [Header("移动参数")]
    public float mouseSensitivity = 3f;
    public float acceleration = 4f; // 加速度(m/s²)
    public float maxSpeed = 8f;     // 最大速度
    public float friction = 1f;     // 摩擦力(m/s²)

    private Vector3 _velocity;      // 世界空间速度向量
    private float _facingYaw;       // 玩家朝向的Y轴旋转角

    void Start()
    {
        _facingYaw = transform.eulerAngles.y;
    }

    void Update()
    {
        float deltaTime = Time.deltaTime;

        // 处理鼠标转向
        float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
        _facingYaw += mouseX;
        transform.localEulerAngles = new Vector3(0, _facingYaw, 0);

        // 获取并归一化键盘输入(避免斜向加速过快)
        float inputForward = Input.GetKey(KeyCode.W) ? 1f : (Input.GetKey(KeyCode.S) ? -1f : 0f);
        float inputRight = Input.GetKey(KeyCode.D) ? 1f : (Input.GetKey(KeyCode.A) ? -1f : 0f);
        Vector2 inputDir = new Vector2(inputRight, inputForward).normalized;

        // 计算本地坐标系的加速度方向
        Vector3 localForward = transform.forward;
        Vector3 localRight = transform.right;
        Vector3 accelDir = localForward * inputDir.y + localRight * inputDir.x;

        // 施加加速度
        _velocity += accelDir * acceleration * deltaTime;

        // 施加反向摩擦力(模拟冰面滑行减速)
        if (_velocity.magnitude > 0.1f)
        {
            Vector3 frictionDir = -_velocity.normalized;
            _velocity += frictionDir * friction * deltaTime;
            // 防止摩擦力反向加速
            if (Vector3.Dot(_velocity, frictionDir) > 0)
            {
                _velocity = Vector3.zero;
            }
        }

        // 限制最大速度
        if (_velocity.magnitude > maxSpeed)
        {
            _velocity = _velocity.normalized * maxSpeed;
        }

        // 更新玩家位置
        transform.position += _velocity * deltaTime;
    }
}

关键改进点

  • 直接维护速度向量:用Vector3存储世界空间速度,避免角度与大小分离带来的方向错位,操作更直观。
  • 统一方向基准:直接使用transform.forward和transform.right获取本地方向,完全匹配Unity坐标系,彻底解决方向不匹配问题。
  • 物理化减速逻辑:施加与速度方向相反的摩擦力,实现自然的滑行效果,方向切换时加速度可平滑改变速度方向,无需等速度归零。
  • 输入归一化处理:斜向输入时归一化向量,避免斜向移动速度过快的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:36:05