158 lines
3.7 KiB
C#
158 lines
3.7 KiB
C#
using Cinemachine;
|
|
using System;
|
|
using System.Runtime.CompilerServices;
|
|
using UnityEngine;
|
|
|
|
namespace TweenAnimation
|
|
{
|
|
public enum ETweenType
|
|
{
|
|
Once,
|
|
Looped,
|
|
PingPong
|
|
}
|
|
|
|
[RequireComponent(typeof(CinemachineSmoothPath)), ExecuteAlways]
|
|
public class TweenPath : MonoBehaviour
|
|
{
|
|
[Serializable]
|
|
public class TweenTarget
|
|
{
|
|
public Transform transform;
|
|
public float startPos;
|
|
}
|
|
|
|
[SerializeReference]
|
|
public TweenTarget[] targets;
|
|
|
|
[SerializeField]
|
|
public CinemachineSmoothPath path;
|
|
|
|
[SerializeField, HideInInspector]
|
|
private Transform minStarPosTransform;
|
|
|
|
[SerializeField]
|
|
public ETweenType TweenType;
|
|
|
|
[Min(0.1f)] public float Duration = 1;
|
|
[Min(0)] public float Delay = 0;
|
|
[SerializeField]
|
|
public AnimationCurve speedCurve = AnimationCurve.Linear(0, 0, 1, 1);
|
|
|
|
private float playTime = 0;
|
|
private bool isPlaying = false;
|
|
|
|
#if UNITY_EDITOR
|
|
public bool isEditing = false;
|
|
#endif
|
|
|
|
private void Awake()
|
|
{
|
|
#if UNITY_EDITOR
|
|
path ??= GetComponent<CinemachineSmoothPath>();
|
|
#endif
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
Play();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
[ContextMenu("Play")]
|
|
#endif
|
|
public void Play()
|
|
{
|
|
isPlaying = true;
|
|
playTime = 0;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
[ContextMenu("Stop")]
|
|
#endif
|
|
public void Stop()
|
|
{
|
|
isPlaying = false;
|
|
playTime = 0;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (targets == null)
|
|
{
|
|
return;
|
|
}
|
|
if (!isEditing && !isPlaying && !Application.isPlaying)
|
|
{
|
|
float minStartPos = 10;
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
var target = targets[i];
|
|
EvaluatePosition(target.transform, target.startPos);
|
|
if (target.startPos < minStartPos)
|
|
{
|
|
minStartPos = target.startPos;
|
|
minStarPosTransform = target.transform;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if (!isPlaying)
|
|
{
|
|
return;
|
|
}
|
|
|
|
playTime += Time.smoothDeltaTime;
|
|
if (playTime < Delay)
|
|
{
|
|
return;
|
|
}
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
var target = targets[i];
|
|
var t = (playTime - Delay) / Duration + target.startPos;
|
|
EvaluatePosition(target.transform, t);
|
|
|
|
if (target.transform == minStarPosTransform && TweenType == ETweenType.Once && t >= 1)
|
|
{
|
|
Stop();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void EvaluatePosition(Transform transform, float t)
|
|
{
|
|
if (TweenType == ETweenType.Looped)
|
|
{
|
|
t = t % 1.0f;
|
|
}
|
|
else if (TweenType == ETweenType.PingPong)
|
|
{
|
|
if (((int)t & 1) == 0)
|
|
{
|
|
t = t % 1.0f;
|
|
}
|
|
else
|
|
{
|
|
t = 1f - (t % 1.0f);
|
|
}
|
|
}
|
|
|
|
var p = speedCurve.Evaluate(t);
|
|
|
|
p = p * (path.MaxPos - path.MinPos);
|
|
|
|
transform.localPosition = path.EvaluateLocalPosition(p);
|
|
}
|
|
}
|
|
}
|