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
相关产品推荐
相关产品推荐

