Unity无物理组件实现连续瓦片跳跃及旋转异常修复求助
问题修复方案
核心问题分析
- 连续跳跃高度异常:原代码中
CalculateArcHeight错误修改了持久化的targetArcHeight,导致后续跳跃高度基于错误累积值,而非设定的arcHeight。 - 旋转X轴卡死:
Quaternion.LookRotation会生成包含X轴的旋转,玩家只需要绕Y轴转向,多余的X轴旋转累积引发异常。
修改后的完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { private PlayerControls controls; Vector3 _startPosition; Vector3 lastPosition; Quaternion targetRotation; bool jumping = false; public AudioSource audioListener; public AudioClip JumpSound; public float rayLength = 1.4f; // 修正拼写错误:rayLenght → rayLength public LayerMask groundLayer; float parabola = 0f; float _stepScale; float _progress; public float speed; public float arcHeight; Vector3 targetDestination; private float targetArcHeight; // 仅用于当前跳跃的临时高度 private bool ableToJump = true; private void Awake() { controls = new PlayerControls(); } private void OnEnable() { controls.Enable(); } private void OnDisable() { controls.Disable(); } void Start() { controls.Main.Movement.performed += ctx => Move(ctx.ReadValue<Vector2>()); lastPosition = transform.position; targetRotation = transform.rotation; // 初始化旋转为当前值,避免初始帧跳变 } private void Move(Vector2 direction) { if (ableToJump) { _progress = 0f; ableToJump = false; _startPosition = transform.position; // 修复:直接使用设定的arcHeight作为当前跳跃的相对高度 targetArcHeight = arcHeight; Vector3 movement = new Vector3(direction.x, 0, direction.y); // 修复:目标位置基于当前起跳位置,而非lastPosition targetDestination = _startPosition + movement; lastPosition = targetDestination; float distance = Vector3.Distance(_startPosition, targetDestination); _stepScale = speed / distance; audioListener.PlayOneShot(JumpSound); // 修复旋转:仅保留Y轴转向,X/Z轴旋转清零 Vector3 lookDir = targetDestination - _startPosition; lookDir.y = 0; // 忽略Y轴差异,只计算水平转向 targetRotation = Quaternion.LookRotation(lookDir); jumping = true; } } void Update() { if (jumping) { _progress = Mathf.Min(_progress + Time.deltaTime * _stepScale, 1.0f); parabola = 1.0f - 4.0f * (_progress - 0.5f) * (_progress - 0.5f); Vector3 nextPos = Vector3.Lerp(_startPosition, targetDestination, _progress); // 抛物线高度是相对于起跳位置的增量,直接叠加即可 nextPos.y += parabola * targetArcHeight; transform.position = nextPos; // 跳跃后期允许再次起跳 if (_progress >= 0.6f) { ableToJump = true; } // 跳跃完全结束后重置状态 if (_progress >= 1.0f) { jumping = false; } } // 平滑旋转,仅应用Y轴旋转 transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 10f * Time.deltaTime); } // 移除错误的CalculateArcHeight方法 }
关键修改点说明
- 跳跃高度修复:删除
CalculateArcHeight,每次跳跃直接将targetArcHeight设为arcHeight,确保所有跳跃的相对高度都是设定值;同时修正目标位置计算逻辑,基于当前起跳位置而非lastPosition,避免连续跳跃偏移。 - 旋转问题修复:计算转向方向时忽略Y轴差异,生成的旋转仅包含Y轴角度,确保玩家只会水平转向,不会出现X轴旋转异常。
- 细节优化:修正变量拼写错误,初始化旋转值避免初始帧跳变,增加跳跃结束后的状态重置逻辑。
内容的提问来源于stack exchange,提问作者Димитър Димитров
相关产品推荐
相关产品推荐

