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

添加Character Controller后角色移动时上浮0.08单位的问题

问题:添加Character Controller后角色启动移动时上浮0.08单位

为角色添加Character Controller组件后,仅在开始移动时会向上浮起0.08单位,碰撞器位置显示正常。

相关截图

  • 带有Character Controller组件的角色:
    带有Character Controller组件的角色
  • 角色设置面板:
    角色设置面板

角色移动代码

[SerializeField] private Transform _orientation;

private CharacterController _controller;

private float xInput;
private float yInput;

private Vector3 _moveDirection;

private float rotationSpeed = 10f;
private float speed = 5f;

private void Awake()
{
    _controller = GetComponent<CharacterController>();
}

private void Start()
{
    Cursor.lockState = CursorLockMode.Locked;
}

private void Update()
{
    xInput = Input.GetAxis("Horizontal");
    yInput = Input.GetAxis("Vertical");

    _moveDirection = _orientation.forward * yInput + _orientation.right * xInput;

    RotatePlayerToCameraView();
    Move(_moveDirection);
}

private void RotatePlayerToCameraView()
{
    Vector3 viewDirection = transform.position - new Vector3(_orientation.position.x, transform.position.y, _orientation.position.z);
    _orientation.forward = viewDirection.normalized; // 待理解此行作用

    gameObject.transform.forward = Vector3.Slerp(gameObject.transform.forward, viewDirection.normalized, Time.deltaTime * rotationSpeed);
}

private void Move(Vector3 moveDirection)
{
    float scaledMoveSpeed = speed * Time.deltaTime;

    moveDirection = new Vector3(moveDirection.x, 0, moveDirection.z);

    _controller.Move(moveDirection * scaledMoveSpeed);
}

问题排查与解决方法

1. 调整Character Controller的Skin Width参数

Character Controller默认的Skin Width为0.08,这刚好和你遇到的上浮数值匹配。该参数用于碰撞检测的缓冲,值过大时,首次移动可能触发角色位置校正导致上浮。

  • 在Inspector面板中找到Character Controller组件,将Skin Width调至0.04左右(不要设为0,否则会丢失碰撞缓冲),测试是否解决问题。

2. 添加重力模拟,确保角色贴合地面

当前代码完全忽略了重力,Character Controller不会自动处理重力,导致角色无法稳定贴合地面,移动时易出现位置偏移。修改Move方法,加入重力逻辑:

private float gravity = -9.81f;
private Vector3 _velocity;

private void Move(Vector3 moveDirection)
{
    float scaledMoveSpeed = speed * Time.deltaTime;

    // 地面贴合处理:角色在地面时重置重力速度,轻微下压避免浮空
    if (_controller.isGrounded && _velocity.y < 0)
    {
        _velocity.y = -2f;
    }
    _velocity.y += gravity * Time.deltaTime;

    // 确保移动方向为单位向量,避免斜向移动速度过快
    moveDirection = new Vector3(moveDirection.x, 0, moveDirection.z).normalized;
    
    // 同时应用移动速度和重力
    _controller.Move((moveDirection * scaledMoveSpeed) + _velocity * Time.deltaTime);
}

添加重力后,角色会持续受到向下的力,始终贴合地面,从根源避免移动时的上浮现象。

3. 检查初始位置是否存在间隙

确认角色Transform的Y轴位置是否让Character Controller底部与地面存在微小间隙。可以手动调整角色Y轴位置,让碰撞器底部刚好接触地面,减少首次移动时的位置校正触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:10:34