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

Unity 3D角色朝移动方向即时旋转且保持位置的实现问题

问题:Unity中角色朝移动方向即时旋转且保持位置不变

我有一个类似需求:在Unity 3D中让角色朝移动方向旋转,但需保持位置移动逻辑稳定且完成即时旋转——由于使用了程序化迷宫,空间不足以支持大半径的渐变转向。下方是我的代码尝试,其中第二种尝试报错:viewing vector is zero。观察四张截图可知,当绕y轴旋转时,x轴和z轴位移方向会跳变,移动时角色看起来像是在迷宫中瞬移。请问如何实现旋转时位置移动逻辑稳定?

向右旋转效果:
向右旋转效果

向前旋转效果:
向前旋转效果

向左旋转效果:
向左旋转效果

向后旋转效果:
向后旋转效果

代码尝试1

public void playerMovement()
{
    float horizontalInput = Input.GetAxis("Horizontal");
    float verticalInput = Input.GetAxis("Vertical");

    Vector3 movementx = new Vector3(horizontalInput, 0f, 0f);
    Vector3 movementy = new Vector3(0f, 0f, verticalInput);
  
    movementy = transform.forward * verticalInput;
    movementx = transform.right * horizontalInput;

    if (horizontalInput > 0)
    {
        transform.eulerAngles = new Vector3(0f, 90f, 0f);
        transform.Translate(-movementx.normalized * 0.1f, Space.Self);
    }

    if (horizontalInput < 0)
    {
        transform.eulerAngles = new Vector3(0f, 270f, 0f);
        transform.Translate(-movementx.normalized * 0.1f, Space.Self);
    }

    if (verticalInput < 0)
    {
        transform.eulerAngles = new Vector3(0f, 180f, 0f);
        transform.Translate(movementy.normalized * 0.1f, Space.Self);
    }

    if (verticalInput > 0)
    {
        transform.eulerAngles = new Vector3(0f, 0f, 0f);
        transform.Translate(movementy.normalized * 0.1f, Space.Self);
    }
}

代码尝试2

public void playerMovement2()
{
    Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
    movement = transform.TransformDirection(movement);
    transform.Translate(movement.normalized * 0.1f, Space.Self);
    transform.rotation = Quaternion.LookRotation(movement);
}

解决方案

核心问题分析

  • 代码1中使用Space.Self位移,旋转后局部轴方向改变,导致位移方向跳变,出现瞬移感。
  • 代码2报错是因为无输入时movement为零向量,Quaternion.LookRotation无法处理零向量。

修正后的基础实现

先根据输入确定世界空间下的目标方向,即时旋转角色,再用世界空间位移保证移动方向与输入一致:

public void FixedUpdate() // 推荐用FixedUpdate处理移动逻辑
{
    float horizontal = Input.GetAxis("Horizontal");
    float vertical = Input.GetAxis("Vertical");

    // 过滤微小输入,避免无操作时触发逻辑
    if (Mathf.Abs(horizontal) > 0.1f || Mathf.Abs(vertical) > 0.1f)
    {
        // 构建世界空间的移动方向
        Vector3 targetDirection = new Vector3(horizontal, 0f, vertical).normalized;

        // 即时旋转到目标方向(仅绕Y轴)
        transform.rotation = Quaternion.LookRotation(targetDirection, Vector3.up);

        // 按世界方向移动,不受旋转影响
        transform.Translate(targetDirection * 0.1f, Space.World);
    }
}

程序化迷宫适配(格子移动)

如果是格子化迷宫,可限制移动为整格步长,避免半格位移:

public float gridSize = 1f; // 迷宫格子尺寸
private bool isMoving = false;

public void Update()
{
    if (isMoving) return;

    // 使用GetAxisRaw获取整数输入,避免渐变
    float horizontal = Input.GetAxisRaw("Horizontal");
    float vertical = Input.GetAxisRaw("Vertical");

    if (horizontal != 0 || vertical != 0)
    {
        Vector3 targetDirection = new Vector3(horizontal, 0f, vertical).normalized;
        // 即时旋转
        transform.rotation = Quaternion.LookRotation(targetDirection, Vector3.up);
        // 移动到下一格
        StartCoroutine(MoveToNextGrid(targetDirection));
    }
}

private IEnumerator MoveToNextGrid(Vector3 direction)
{
    isMoving = true;
    Vector3 targetPosition = transform.position + direction * gridSize;
    // 平滑移动到目标格子(也可直接赋值position实现瞬移)
    while (Vector3.Distance(transform.position, targetPosition) > 0.01f)
    {
        transform.position = Vector3.MoveTowards(transform.position, targetPosition, 5f * Time.deltaTime);
        yield return null;
    }
    transform.position = targetPosition;
    isMoving = false;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 15:51:00