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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:32:23