UnityCommon/Aniatioon/SpriteAnimator.cs

218 lines
6.1 KiB
C#
Raw Normal View History

2024-12-12 17:06:08 +08:00
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// <20><>ʾһ<CABE><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>һϵ<D2BB>о<EFBFBD><D0BE><EFBFBD><EFBFBD><EFBFBD>ÿ֡<C3BF><D6A1><EFBFBD><EFBFBD>ʾʱ<CABE>
/// </summary>
[System.Serializable]
public class AnimationSequence
{
[Tooltip("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еľ<D0B5><C4BE><EFBFBD><EFBFBD>б<EFBFBD>")]
public List<Sprite> sprites = new List<Sprite>();
[Tooltip("ÿһ֡<D2BB><D6A1>ʱ<EFBFBD><EFBFBD><E4A3AC>λ<EFBFBD><CEBB>")]
public float frameTime = 0.1f; // ÿ֡<C3BF>ij<EFBFBD><C4B3><EFBFBD>ʱ<EFBFBD><EFBFBD>
}
/// <summary>
/// <20><><EFBFBD>ƾ<EFBFBD><C6BE><EFBFBD><E9B6AF><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><C5B5>ʹ<E0A3AC><CAB9> Dictionary <20><><EFBFBD>о<EFBFBD><D0BE><EFBFBD><E9BBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public class SpriteAnimator : MonoBehaviour
{
/// <summary>
/// <20><><EFBFBD><EFBFBD><E5B6AF><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
/// </summary>
public enum LoopType
{
Loop, // <20><><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
Once, // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>
PingPong // <20><><EFBFBD>ز<EFBFBD><D8B2><EFBFBD>
}
[Header("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>")]
[Tooltip("<22><><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
public List<AnimationSequence> animationSequences = new List<AnimationSequence>();
[Header("SpriteRenderer<65><72><EFBFBD><EFBFBD>")]
[Tooltip("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SpriteRenderer")]
public SpriteRenderer spriteRenderer;
[Header("<22><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
[Tooltip("<22><>ǰ<EFBFBD><C7B0><EFBFBD>ŵĶ<C5B5><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
public int currentAnimationIndex = 0;
[Header("ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
[Tooltip("ѡ<>񶯻<EFBFBD><F1B6AFBB><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
public LoopType loopType = LoopType.Loop;
// <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>
private Dictionary<int, AnimationSequence> animationDictionary = new Dictionary<int, AnimationSequence>();
private AnimationSequence currentAnimation;
private int currentFrameIndex = 0;
private float frameTimer = 0f;
private bool isPlaying = true;
private bool pingPongForward = true;
/// <summary>
/// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
private void Awake()
{
if (animationSequences == null || animationSequences.Count == 0)
{
Debug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>Ϊ<EFBFBD>ա<EFBFBD><D5A1><EFBFBD><EFBFBD><EFBFBD> Inspector <20><><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>");
return;
}
for (int i = 0; i < animationSequences.Count; i++)
{
if (!animationDictionary.ContainsKey(i))
{
animationDictionary.Add(i, animationSequences[i]);
}
else
{
Debug.LogWarning($"<22><><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> {i}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8>");
}
}
SetAnimation(currentAnimationIndex);
}
/// <summary>
/// <20>ڿ<EFBFBD>ʼʱ<CABC><CAB1><EFBFBD>г<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
/// </summary>
private void Start()
{
if (spriteRenderer == null)
{
Debug.LogError("SpriteRenderer 'spriteRenderer' Ϊ<>ա<EFBFBD><D5A1><EFBFBD><EFBFBD><EFBFBD> Inspector <20>з<EFBFBD><D0B7><EFBFBD> SpriteRenderer<65><72>");
return;
}
if (currentAnimation != null && currentAnimation.sprites.Count > 0)
{
frameTimer = currentAnimation.frameTime;
spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex];
}
else
{
Debug.LogError("<22><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ջ򲻰<D5BB><F2B2BBB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>顣");
}
}
/// <summary>
/// ÿ֡<C3BF><D6A1><EFBFBD><EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>š<EFBFBD>
/// </summary>
private void Update()
{
if (!isPlaying || currentAnimation == null || currentAnimation.sprites.Count == 0)
return;
frameTimer -= Time.deltaTime;
if (frameTimer <= 0f)
{
AdvanceFrame();
frameTimer = currentAnimation.frameTime;
}
}
/// <summary>
/// <20><><EFBFBD>õ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ŵĶ<C5B5><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
/// </summary>
/// <param name="index"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
public void SetAnimation(int index)
{
if (animationDictionary.TryGetValue(index, out AnimationSequence selectedAnimation))
{
currentAnimation = selectedAnimation;
currentFrameIndex = 0;
pingPongForward = true;
frameTimer = currentAnimation.frameTime;
if (currentAnimation.sprites.Count > 0)
{
spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex];
}
else
{
Debug.LogWarning($"ѡ<>еĶ<D0B5><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> {index} û<>а<EFBFBD><D0B0><EFBFBD><EFBFBD>κξ<CEBA><CEBE>顣");
}
}
else
{
Debug.LogError($"SetAnimation: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> {index} <20><> animationDictionary <20><>δ<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>");
}
}
/// <summary>
/// <20><><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2>ź<EFBFBD><C5BA><EFBFBD>ͣ<EFBFBD><CDA3>
/// </summary>
/// <param name="play">true: <20><><EFBFBD>Ŷ<EFBFBD><C5B6><EFBFBD>, false: <20><>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD></param>
public void PlayPauseAnimation(bool play)
{
isPlaying = play;
if (isPlaying && currentAnimation != null && currentAnimation.sprites.Count > 0)
{
// ȷ<><C8B7><EFBFBD><EFBFBD>ǰ֡<C7B0><D6A1>ʾ<EFBFBD><CABE>ȷ
spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex];
frameTimer = currentAnimation.frameTime;
}
}
/// <summary>
/// ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CDB4><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
private void AdvanceFrame()
{
switch (loopType)
{
case LoopType.Loop:
currentFrameIndex = (currentFrameIndex + 1) % currentAnimation.sprites.Count;
break;
case LoopType.Once:
currentFrameIndex = Mathf.Min(currentFrameIndex + 1, currentAnimation.sprites.Count - 1);
if (currentFrameIndex == currentAnimation.sprites.Count - 1)
{
isPlaying = false; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϻ<EFBFBD>ֹͣ
}
break;
case LoopType.PingPong:
if (pingPongForward)
{
currentFrameIndex++;
if (currentFrameIndex >= currentAnimation.sprites.Count - 1)
{
currentFrameIndex = currentAnimation.sprites.Count - 1;
pingPongForward = false;
}
}
else
{
currentFrameIndex--;
if (currentFrameIndex <= 0)
{
currentFrameIndex = 0;
pingPongForward = true;
}
}
break;
}
spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex];
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
private void OnDestroy()
{
animationDictionary.Clear();
animationSequences = null;
currentAnimation = null;
}
}