如何在C#与Unity中延伸二次插值生成的运动曲线?
问题核心原因
- 插值计算使用
%1f取模,interpolateAmount超过1后会重置为0,导致石块位置跳回曲线起点,出现循环往返的问题 - 原代码每帧读取实时
playerPosition计算曲线,玩家移动后曲线终点会实时偏移;且碰撞逻辑未筛选碰撞体,只要触发碰撞就销毁,导致石块未落地就被提前删除
修复方案
步骤1:修改曲线运动逻辑
移除取模逻辑,插值超过1后切换为惯性运动,同时缓存石块生成时的玩家位置作为固定曲线终点,避免玩家移动导致曲线偏移。
// 新增需要声明的变量 private Rigidbody2D rb; // 缓存石块生成时的玩家位置,作为固定曲线终点 private Vector3 initialPlayerPosition; // 标记曲线运动是否结束 private bool isCurveCompleted = false; private void Awake() { rb = GetComponent<Rigidbody2D>(); initialPlayerPosition = playerPosition; // 曲线运动阶段关闭重力,避免干扰插值位置 rb.gravityScale = 0; } private void FollowQuadraticPath() { if (isCurveCompleted) return; // 移除%1f取模,避免插值循环 interpolateAmount += Time.deltaTime; // 插值到终点后切换为物理惯性运动 if (interpolateAmount >= 1f) { interpolateAmount = 1f; // 计算曲线终点的切线方向,作为后续飞射的初速度方向 Vector3 curveEndTangent = (pointBC.transform.position - pointAB.transform.position).normalized; // 可根据手感调整速度倍率 float throwSpeed = 5f; // 开启重力,施加初速度 rb.gravityScale = 1; rb.velocity = curveEndTangent * throwSpeed; isCurveCompleted = true; // 提前销毁不需要的辅助点 Destroy(pointABInstance); Destroy(pointBCInstance); return; } pointAB.transform.position = Vector3.Lerp(transformerPosition, throwHeightPosition, interpolateAmount); // 用缓存的初始玩家位置计算曲线,不要用实时playerPosition pointBC.transform.position = Vector3.Lerp(throwHeightPosition, initialPlayerPosition, interpolateAmount); transform.position = Vector3.Lerp(pointAB.transform.position, pointBC.transform.position, interpolateAmount); }
步骤2:修改碰撞销毁逻辑
仅在碰到玩家或地面时销毁石块,避免碰到其他物体提前销毁。
private void OnCollisionEnter2D(Collision2D collision) { // 碰到玩家造成伤害后销毁 if (collision.gameObject.TryGetComponent<PlayerHealth>(out var playerHealth)) { playerHealth.DealDamage(damage); DestroySelf(); return; } // 碰到地面后销毁,可替换为你项目的地面Layer判断逻辑 if (collision.gameObject.CompareTag("Ground")) { DestroySelf(); } } // 封装销毁逻辑,避免重复代码 private void DestroySelf() { if (pointABInstance != null) Destroy(pointABInstance); if (pointBCInstance != null) Destroy(pointBCInstance); Destroy(gameObject); }
注意事项
- 需提前给地面物体设置对应Tag(比如
Ground)或专属Layer,避免石块误触其他场景物体提前销毁 - 速度倍率、重力缩放值可根据游戏需求调整,保证石块飞出去后的运动轨迹符合手感预期
- 如果不需要重力影响的抛物轨迹,可保持
rb.gravityScale = 0,石块会沿曲线切线方向匀速直线运动,直到碰到碰撞体
内容的提问来源于stack exchange,提问作者Njal_Inferno
相关产品推荐
相关产品推荐

