2D俯视角史莱姆跳跃效果实现问题求助
解决史莱姆2D俯视角跳跃问题
原代码的核心问题
- 用X位置进度驱动正弦波,会导致跳跃节奏随目标距离乱掉:近目标时跳跃没完成就落地,远目标时可能反复上下波动,不符合真实跳跃“一次起跳-落地”的逻辑
- 正弦波是对称运动,没模拟真实跳跃的重力加速度(上升减速、下落加速),动作显得生硬假
- 直接硬写Y值,没和移动进度绑定,跳跃与移动的同步性差
方案1:协程+抛物线公式(无物理交互)
用协程控制完整跳跃流程,基于时间进度计算抛物线位置,保证跳跃节奏统一,同时模拟重力感。
示例代码:
private bool isJumping = false; public float jumpHeight = 1f; // 跳跃峰值高度 public float jumpDuration = 0.5f; // 单次跳跃总时长 public void JumpToTarget(Vector3 targetPos) { if (isJumping) return; StartCoroutine(JumpCoroutine(targetPos)); } private IEnumerator JumpCoroutine(Vector3 targetPos) { isJumping = true; Vector3 startPos = transform.position; float elapsedTime = 0f; while (elapsedTime < jumpDuration) { elapsedTime += Time.deltaTime; float progress = Mathf.Clamp01(elapsedTime / jumpDuration); // 匀速计算X轴位置 float currentX = Mathf.Lerp(startPos.x, targetPos.x, progress); // 抛物线Y轴高度:顶点在进度0.5处,符合重力下落逻辑 float currentY = startPos.y + 4 * jumpHeight * progress * (1 - progress); transform.position = new Vector3(currentX, currentY, transform.position.z); yield return null; } // 强制修正最终位置,避免误差 transform.position = targetPos; isJumping = false; }
点击触发逻辑:
void Update() { if (Input.GetMouseButtonDown(0)) { Vector3 targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); targetPos.z = transform.position.z; // 保持俯视角Z轴一致 JumpToTarget(targetPos); } }
方案2:使用Rigidbody2D(带物理交互)
如果需要史莱姆和场景碰撞体交互(比如碰障碍停下、掉坑),直接用物理系统更真实。
步骤:给史莱姆添加Rigidbody2D组件,设置合适的Gravity Scale,取消Fixed Angle(需要史莱姆形变/旋转的话)。
示例代码:
private Rigidbody2D rb; public float gravityScale = 2f; void Awake() { rb = GetComponent<Rigidbody2D>(); rb.gravityScale = gravityScale; } void Update() { // 只有在地面(Y轴速度为0)时允许跳跃 if (Input.GetMouseButtonDown(0) && Mathf.Abs(rb.velocity.y) < 0.01f) { Vector3 targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); targetPos.z = transform.position.z; JumpToTarget(targetPos); } } private void JumpToTarget(Vector3 targetPos) { Vector2 direction = targetPos - transform.position; float distance = direction.magnitude; // 物理公式计算跳跃初速度,确保刚好落到目标点(取45度起跳角度) float gravity = Physics2D.gravity.y * rb.gravityScale; float initialVelocity = Mathf.Sqrt(Mathf.Abs(gravity) * distance); rb.velocity = direction.normalized * initialVelocity; }
额外优化建议
- 绑定跳跃动画:根据Y轴速度切换上升/下落动画,或按进度播放弹性形变动画
- 缓动移动:把
Mathf.Lerp换成Mathf.SmoothStep或自定义AnimationCurve,让史莱姆移动更有弹性 - 动态调高度:根据目标距离调整跳跃高度,远目标跳得更高,增强真实感
内容的提问来源于stack exchange,提问作者RedSkull
相关产品推荐
相关产品推荐

