大修
This commit is contained in:
157
Assets/Scripts/SLSUtilities/General/Ease.cs
Normal file
157
Assets/Scripts/SLSUtilities/General/Ease.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SLSUtilities.General
|
||||
{
|
||||
public enum EaseType
|
||||
{
|
||||
Linear,
|
||||
InSine, OutSine, InOutSine,
|
||||
InQuad, OutQuad, InOutQuad,
|
||||
InCubic, OutCubic, InOutCubic,
|
||||
InQuart, OutQuart, InOutQuart,
|
||||
InQuint, OutQuint, InOutQuint,
|
||||
InExpo, OutExpo, InOutExpo,
|
||||
InCirc, OutCirc, InOutCirc,
|
||||
InElastic, OutElastic, InOutElastic,
|
||||
InBack, OutBack, InOutBack,
|
||||
InBounce, OutBounce, InOutBounce,
|
||||
Flash, InFlash, OutFlash, InOutFlash
|
||||
}
|
||||
|
||||
public static class Ease
|
||||
{
|
||||
// 缓存生成的曲线,避免重复计算
|
||||
private static readonly Dictionary<EaseType, AnimationCurve> CurveCache = new Dictionary<EaseType, AnimationCurve>();
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定的缓动曲线
|
||||
/// </summary>
|
||||
public static AnimationCurve GetCurve(EaseType easeType)
|
||||
{
|
||||
if (CurveCache.TryGetValue(easeType, out AnimationCurve cachedCurve))
|
||||
{
|
||||
return cachedCurve;
|
||||
}
|
||||
|
||||
AnimationCurve newCurve = CreateCurve(easeType);
|
||||
CurveCache[easeType] = newCurve;
|
||||
return newCurve;
|
||||
}
|
||||
|
||||
private static AnimationCurve CreateCurve(EaseType easeType)
|
||||
{
|
||||
Keyframe[] keys;
|
||||
// 采样精细度:对于复杂的曲线(如 Elastic, Bounce),采样点需要多一些
|
||||
int samples = IsComplex(easeType) ? 50 : 20;
|
||||
keys = new Keyframe[samples + 1];
|
||||
|
||||
for (int i = 0; i <= samples; i++)
|
||||
{
|
||||
float t = (float)i / samples;
|
||||
float v = Evaluate(easeType, t);
|
||||
keys[i] = new Keyframe(t, v);
|
||||
}
|
||||
|
||||
AnimationCurve curve = new AnimationCurve(keys);
|
||||
|
||||
// 平滑曲线切线(除线性外)
|
||||
if (easeType != EaseType.Linear)
|
||||
{
|
||||
for (int i = 0; i < keys.Length; i++)
|
||||
{
|
||||
curve.SmoothTangents(i, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
private static bool IsComplex(EaseType type)
|
||||
{
|
||||
return type.ToString().Contains("Elastic") ||
|
||||
type.ToString().Contains("Bounce") ||
|
||||
type.ToString().Contains("Flash");
|
||||
}
|
||||
|
||||
// 数学计算核心:标准的 Robert Penner 缓动公式
|
||||
private static float Evaluate(EaseType type, float t)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EaseType.Linear: return t;
|
||||
case EaseType.InSine: return 1f - Mathf.Cos(t * Mathf.PI * 0.5f);
|
||||
case EaseType.OutSine: return Mathf.Sin(t * Mathf.PI * 0.5f);
|
||||
case EaseType.InOutSine: return -(Mathf.Cos(Mathf.PI * t) - 1f) * 0.5f;
|
||||
case EaseType.InQuad: return t * t;
|
||||
case EaseType.OutQuad: return 1f - (1f - t) * (1f - t);
|
||||
case EaseType.InOutQuad: return t < 0.5f ? 2f * t * t : 1f - Mathf.Pow(-2f * t + 2f, 2f) * 0.5f;
|
||||
case EaseType.InCubic: return t * t * t;
|
||||
case EaseType.OutCubic: return 1f - Mathf.Pow(1f - t, 3f);
|
||||
case EaseType.InOutCubic: return t < 0.5f ? 4f * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 3f) * 0.5f;
|
||||
case EaseType.InQuart: return t * t * t * t;
|
||||
case EaseType.OutQuart: return 1f - Mathf.Pow(1f - t, 4f);
|
||||
case EaseType.InOutQuart: return t < 0.5f ? 8f * t * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 4f) * 0.5f;
|
||||
case EaseType.InQuint: return t * t * t * t * t;
|
||||
case EaseType.OutQuint: return 1f - Mathf.Pow(1f - t, 5f);
|
||||
case EaseType.InOutQuint: return t < 0.5f ? 16f * t * t * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 5f) * 0.5f;
|
||||
case EaseType.InExpo: return t == 0f ? 0f : Mathf.Pow(2f, 10f * t - 10f);
|
||||
case EaseType.OutExpo: return t == 1f ? 1f : 1f - Mathf.Pow(2f, -10f * t);
|
||||
case EaseType.InOutExpo:
|
||||
return t == 0f ? 0f : t == 1f ? 1f : t < 0.5f ? Mathf.Pow(2f, 20f * t - 10f) * 0.5f : (2f - Mathf.Pow(2f, -20f * t + 10f)) * 0.5f;
|
||||
case EaseType.InCirc: return 1f - Mathf.Sqrt(1f - Mathf.Pow(t, 2f));
|
||||
case EaseType.OutCirc: return Mathf.Sqrt(1f - Mathf.Pow(t - 1f, 2f));
|
||||
case EaseType.InOutCirc:
|
||||
return t < 0.5f
|
||||
? (1f - Mathf.Sqrt(1f - Mathf.Pow(2f * t, 2f))) * 0.5f
|
||||
: (Mathf.Sqrt(1f - Mathf.Pow(-2f * t + 2f, 2f)) + 1f) * 0.5f;
|
||||
case EaseType.InBack:
|
||||
{
|
||||
const float s = 1.70158f;
|
||||
return (s + 1f) * t * t * t - s * t * t;
|
||||
}
|
||||
case EaseType.OutBack:
|
||||
{
|
||||
const float s = 1.70158f;
|
||||
return 1f + (s + 1f) * Mathf.Pow(t - 1f, 3f) + s * Mathf.Pow(t - 1f, 2f);
|
||||
}
|
||||
case EaseType.InOutBack:
|
||||
{
|
||||
const float s = 1.70158f * 1.525f;
|
||||
return t < 0.5f
|
||||
? (Mathf.Pow(2f * t, 2f) * ((s + 1f) * 2f * t - s)) * 0.5f
|
||||
: (Mathf.Pow(2f * t - 2f, 2f) * ((s + 1f) * (t * 2f - 2f) + s) + 2f) * 0.5f;
|
||||
}
|
||||
case EaseType.InElastic:
|
||||
return t == 0f ? 0f : t == 1f ? 1f : -Mathf.Pow(2f, 10f * t - 10f) * Mathf.Sin((t * 10f - 10.75f) * ((2f * Mathf.PI) / 3f));
|
||||
case EaseType.OutElastic:
|
||||
return t == 0f ? 0f : t == 1f ? 1f : Mathf.Pow(2f, -10f * t) * Mathf.Sin((t * 10f - 0.75f) * ((2f * Mathf.PI) / 3f)) + 1f;
|
||||
case EaseType.InOutElastic:
|
||||
const float c5 = (2f * Mathf.PI) / 4.5f;
|
||||
return t == 0f ? 0f :
|
||||
t == 1f ? 1f :
|
||||
t < 0.5f ? -(Mathf.Pow(2f, 20f * t - 10f) * Mathf.Sin((20f * t - 11.125f) * c5)) * 0.5f :
|
||||
(Mathf.Pow(2f, -20f * t + 10f) * Mathf.Sin((20f * t - 11.125f) * c5)) * 0.5f + 1f;
|
||||
case EaseType.InBounce: return 1f - Evaluate(EaseType.OutBounce, 1f - t);
|
||||
case EaseType.OutBounce:
|
||||
if (t < 1f / 2.75f) return 7.5625f * t * t;
|
||||
else if (t < 2f / 2.75f) return 7.5625f * (t -= 1.5f / 2.75f) * t + 0.75f;
|
||||
else if (t < 2.5f / 2.75f) return 7.5625f * (t -= 2.25f / 2.75f) * t + 0.9375f;
|
||||
else return 7.5625f * (t -= 2.625f / 2.75f) * t + 0.984375f;
|
||||
case EaseType.InOutBounce:
|
||||
return t < 0.5f
|
||||
? (1f - Evaluate(EaseType.OutBounce, 1f - 2f * t)) * 0.5f
|
||||
: (1f + Evaluate(EaseType.OutBounce, 2f * t - 1f)) * 0.5f;
|
||||
|
||||
// Flash 效果通常指类似锯齿波的闪烁,这里模仿 DOTween 的 Flash 逻辑(快速往复)
|
||||
case EaseType.Flash: return Mathf.Abs(Mathf.Cos(t * Mathf.PI * 4f)); // 简单的往复采样
|
||||
case EaseType.InFlash: return t * Mathf.Abs(Mathf.Cos(t * Mathf.PI * 4f));
|
||||
case EaseType.OutFlash: return (1f - t) * Mathf.Abs(Mathf.Cos(t * Mathf.PI * 4f));
|
||||
case EaseType.InOutFlash: return Mathf.SmoothStep(0, 1, t) * Mathf.Abs(Mathf.Cos(t * Mathf.PI * 4f));
|
||||
|
||||
default: return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user