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

Unity C#中使用Vector3.Slerp移动角色出现曲线偏移问题排查

问题:使用Vector3.Slerp实现玩家移动时出现轴偏差

我写了一段代码,想用Slerp让玩家在X轴和Z轴上以10单位为增量移动,但现在Slerp的设置有问题。比如起始位置是(10, 1, 0),目标位置是(20, 1, 0)时,移动过程中玩家的Y轴和Z轴会出现微小偏差,但起止位置完全正确,问题肯定出在Slerp本身。我忽略了什么导致移动出现曲线?

代码片段

...
public void Forward(InputAction.CallbackContext context){ 
        

        if (context.started && Rotating == false && Moving == false) { // 检查玩家是否可以移动
                percentageComplete = 0; // 插值进度百分比
                startPosition = rb.transform.position;
                endPosition = rb.transform.position + rb.transform.rotation * Vector3.forward * 10;

                endPosition[1] = 1;
                endPosition[0] = Mathf.Round(endPosition[0]);
                endPosition[2] = Mathf.Round(endPosition[2]);
                CheckPOS(); // 检查目标位置是否合法,合法则将Moving设为true
                }    
            }
...
    public void Update() { 

    if (Moving == true){
        if (percentageComplete < 1) {
            elapsedTime += Time.deltaTime;
            percentageComplete = elapsedTime / desiredDuration;
            rb.transform.position = Vector3.Slerp(startPosition, endPosition, percentageComplete);
        if (percentageComplete > 1) {
            posX = Mathf.Round(rb.transform.position.x / 10);
            posY = Mathf.Round(rb.transform.position.z / 10);
            rb.transform.position = new Vector3(posX * 10, 1, posY * 10);
            Moving = false;
                              }}

                       }

                   }

问题原因

Vector3.Slerp是球面插值函数,它的作用是将两个三维点当作球面上的点,沿着球面弧线完成插值,而非直线。即使你的起止点在同一平面(Y=1),Slerp也会默认以原点为球心计算弧线路径,这就导致移动过程中Y轴、Z轴出现微小偏差——因为它走的不是两点之间的直线。

解决方案

如果需要的是两点间的直线移动,直接替换成线性插值函数Vector3.Lerp即可,它会严格沿着起止点的直线路径插值,不会出现轴偏差。修改后的Update方法代码如下:

public void Update() { 
    if (Moving == true){
        if (percentageComplete < 1) {
            elapsedTime += Time.deltaTime;
            percentageComplete = elapsedTime / desiredDuration;
            // 替换为线性插值
            rb.transform.position = Vector3.Lerp(startPosition, endPosition, percentageComplete);
            if (percentageComplete > 1) {
                posX = Mathf.Round(rb.transform.position.x / 10);
                posY = Mathf.Round(rb.transform.position.z / 10);
                rb.transform.position = new Vector3(posX * 10, 1, posY * 10);
                Moving = false;
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Chris W.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 10:57:33