如何在Unity C#中为桌游实现不同距离的程序化跳跃?
程序化跳跃实现方案(Unity C#)
一、为什么Vector3.Slerp效果不符合预期
Vector3.Slerp是球面插值函数,它会在两个点之间沿球面曲线移动,适合旋转、圆弧轨迹类需求,但完全不适合模拟符合重力的跳跃运动——这就是你用它做跳跃效果差的核心原因。如果非要基于Slerp调整,需要额外叠加高度方向的插值,但性价比极低,不推荐。
二、推荐实现方案:数学驱动的抛物线跳跃(精确可控)
这种方案完全通过数学计算逐帧更新位置,能精准控制跳跃距离、高度和时长,适合桌游里的触发式跳跃需求,直接用协程即可实现脚本调用。
核心思路
- 计算起点到终点的水平方向位移,保持匀速移动
- 基于时间计算垂直方向的抛物线高度(模拟重力加速度)
- 用协程在每一帧更新玩家位置,直到到达终点
示例代码
using UnityEngine; using System.Collections; public class PlayerJump : MonoBehaviour { // 跳跃的最大高度 public float jumpHeight = 1.5f; // 跳跃全程的时长(秒) public float jumpDuration = 0.8f; // 外部调用的跳跃方法,传入目标点 public void JumpTo(Vector3 targetPos) { StopCoroutine(JumpCoroutine(targetPos)); StartCoroutine(JumpCoroutine(targetPos)); } private IEnumerator JumpCoroutine(Vector3 targetPos) { Vector3 startPos = transform.position; float elapsedTime = 0f; // 计算水平方向的单位向量和总距离 Vector3 horizontalDir = new Vector3(targetPos.x - startPos.x, 0, targetPos.z - startPos.z); float horizontalDistance = horizontalDir.magnitude; Vector3 horizontalMoveDir = horizontalDir.normalized; while (elapsedTime < jumpDuration) { // 计算当前时间进度(0到1) float t = elapsedTime / jumpDuration; // 水平方向匀速移动 float horizontalProgress = horizontalDistance * t; // 垂直方向抛物线计算(二次曲线模拟重力下落) float verticalProgress = 4 * jumpHeight * t * (1 - t); // 更新玩家位置 transform.position = startPos + horizontalMoveDir * horizontalProgress + Vector3.up * verticalProgress; elapsedTime += Time.deltaTime; yield return null; } // 确保最后精准落到目标点 transform.position = targetPos; } }
使用说明
- 触发跳跃时直接调用方法即可,比如检测到跳跃点时:
// 假设jumpPoint是获取到的目标跳跃点Transform GetComponent<PlayerJump>().JumpTo(jumpPoint.position); - 调整
jumpHeight和jumpDuration参数,可以适配不同距离的跳跃手感
三、备选方案:物理系统驱动的跳跃
如果需要跳跃过程中能和场景物理交互(比如碰到障碍物中断),可以用Rigidbody实现:
using UnityEngine; public class PlayerPhysicsJump : MonoBehaviour { private Rigidbody rb; public float jumpHeight = 1.5f; void Awake() { rb = GetComponent<Rigidbody>(); // 锁定旋转,避免跳跃时翻滚 rb.freezeRotation = true; } public void JumpTo(Vector3 targetPos) { Vector3 dir = targetPos - transform.position; float horizontalDistance = new Vector3(dir.x, 0, dir.z).magnitude; // 计算需要的初速度(基于物理公式推导) float timeToReach = 0.8f; float horizontalSpeed = horizontalDistance / timeToReach; float verticalSpeed = Mathf.Sqrt(2 * Physics.gravity.magnitude * jumpHeight); Vector3 velocity = new Vector3(dir.x, 0, dir.z).normalized * horizontalSpeed + Vector3.up * verticalSpeed; rb.velocity = velocity; } }
内容的提问来源于stack exchange,提问作者Wayfarer
相关产品推荐
相关产品推荐

