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

如何外推AnimationCurve?求支持外推的无尽游戏平衡曲线编辑器

实现AnimationCurve外推及XY互推的方案

一、给AnimationCurve添加外推逻辑

Unity的AnimationCurve默认WrapMode确实不支持外推,你可以通过扩展方法手动实现,核心思路是:当X超出曲线关键帧的范围时,基于首尾两段的斜率做线性外推(也可扩展为指数等其他方式),同时保留原曲线在[0,1]范围内的求值逻辑。

示例代码(C#):

using UnityEngine;

public static class AnimationCurveExtensions
{
    // 带外推的Y值计算
    public static float EvaluateWithExtrapolation(this AnimationCurve curve, float x)
    {
        var keys = curve.keys;
        if (keys.Length == 0) return 0f;
        if (keys.Length == 1) return keys[0].value;

        float minX = keys[0].time;
        float maxX = keys[^1].time;

        if (x <= minX)
        {
            // 左外推:取前两个关键帧计算斜率
            Keyframe k0 = keys[0];
            Keyframe k1 = keys[1];
            float slope = (k1.value - k0.value) / (k1.time - k0.time);
            return k0.value + slope * (x - k0.time);
        }
        else if (x >= maxX)
        {
            // 右外推:取最后两个关键帧计算斜率
            Keyframe kN_1 = keys[^2];
            Keyframe kN = keys[^1];
            float slope = (kN.value - kN_1.value) / (kN.time - kN_1.time);
            return kN.value + slope * (x - kN.time);
        }
        else
        {
            // 原曲线范围内正常求值
            return curve.Evaluate(x);
        }
    }

    // Y反推X(支持外推区间)
    public static float ReverseEvaluateWithExtrapolation(this AnimationCurve curve, float y)
    {
        var keys = curve.keys;
        if (keys.Length == 0) return 0f;
        if (keys.Length == 1) return keys[0].time;

        float minY = Mathf.Min(keys[0].value, keys[^1].value);
        float maxY = Mathf.Max(keys[0].value, keys[^1].value);

        if (y <= minY)
        {
            if (keys[0].value <= keys[^1].value)
            {
                Keyframe k0 = keys[0];
                Keyframe k1 = keys[1];
                float slope = (k1.value - k0.value) / (k1.time - k0.time);
                return k0.time + (y - k0.value) / slope;
            }
            else
            {
                Keyframe kN_1 = keys[^2];
                Keyframe kN = keys[^1];
                float slope = (kN.value - kN_1.value) / (kN.time - kN_1.time);
                return kN.time + (y - kN.value) / slope;
            }
        }
        else if (y >= maxY)
        {
            if (keys[0].value >= keys[^1].value)
            {
                Keyframe k0 = keys[0];
                Keyframe k1 = keys[1];
                float slope = (k1.value - k0.value) / (k1.time - k0.time);
                return k0.time + (y - k0.value) / slope;
            }
            else
            {
                Keyframe kN_1 = keys[^2];
                Keyframe kN = keys[^1];
                float slope = (kN.value - kN_1.value) / (kN.time - kN_1.time);
                return kN.time + (y - kN.value) / slope;
            }
        }
        else
        {
            // 曲线范围内遍历查找反推X
            for (int i = 1; i < keys.Length; i++)
            {
                Keyframe prev = keys[i-1];
                Keyframe curr = keys[i];
                if (y >= Mathf.Min(prev.value, curr.value) && y <= Mathf.Max(prev.value, curr.value))
                {
                    float t = Mathf.InverseLerp(prev.value, curr.value, y);
                    return Mathf.Lerp(prev.time, curr.time, t);
                }
            }
        }
        return 0f;
    }
}

说明:

  • 线性外推是最通用的选择,若需要其他外推方式(如指数增长),可修改外推部分的公式。
  • 反推逻辑默认用线性插值,若需更精确结果,可根据关键帧的切线模式(如ClampedAuto、Free)调整插值算法。

二、支持外推的替代工具

如果不想自行编写扩展,这些工具可直接满足需求:

  • Odin Inspector:自带的曲线编辑器支持多种外推模式(线性、恒定、循环等),可视化界面更友好,适合数值平衡调试。
  • Curvy Splines:虽主打样条曲线,但可创建类似AnimationCurve的数值曲线,支持自定义外推规则,还提供更强大的插值和反查功能。
  • Unity Visual Scripting(原Bolt):配合自定义节点,可快速实现带外推的曲线逻辑,无需编写大量代码。

内容的提问来源于stack exchange,提问作者Timothée Dautrême

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:06:26