更新动画控制器

This commit is contained in:
liuliang 2024-12-12 17:51:28 +08:00
parent b109b30ae1
commit 314c5d4c32

View File

@ -2,7 +2,27 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
/// <summary> /// <summary>
/// 表示一个动画序列,包括一系列精灵和每帧的显示时间。 /// 定义动画序列的循环类型。
/// </summary>
public enum MyLoopType
{
Once, // 播放一次
Count, // 播放指定次数
Forever // 无限循环
}
/// <summary>
/// 定义动画组的循环类型。
/// </summary>
public enum GroupLoopType
{
Once, // 动画组循环一次后销毁
Count, // 动画组循环指定次数后销毁
Forever // 动画组无限循环
}
/// <summary>
/// 表示一个动画序列,包括一系列精灵、每帧的显示时间和循环类型。
/// </summary> /// </summary>
[System.Serializable] [System.Serializable]
public class AnimationSequence public class AnimationSequence
@ -12,23 +32,19 @@ public class AnimationSequence
[Tooltip("每一帧的时间,单位秒")] [Tooltip("每一帧的时间,单位秒")]
public float frameTime = 0.1f; // 每帧的持续时间(秒) public float frameTime = 0.1f; // 每帧的持续时间(秒)
[Tooltip("动画序列的循环类型")]
public MyLoopType loopType = MyLoopType.Forever; // 动画序列的循环类型
[Tooltip("动画序列的循环次数(仅当 LoopType 为 Count 时生效)")]
public int loopCount = 1; // 动画序列的循环次数
} }
/// <summary> /// <summary>
/// 控制精灵动画播放的类,使用 Dictionary 进行精灵缓存管理。 /// 控制精灵动画播放的类,支持组循环并允许为每个动画序列设置循环类型和循环次数
/// </summary> /// </summary>
public class SpriteAnimator : MonoBehaviour public class SpriteAnimator : MonoBehaviour
{ {
/// <summary>
/// 定义动画的循环类型。
/// </summary>
public enum LoopType
{
Loop, // 无限循环
Once, // 播放一次
PingPong // 来回播放
}
[Header("动画序列列表")] [Header("动画序列列表")]
[Tooltip("所有动画序列")] [Tooltip("所有动画序列")]
public List<AnimationSequence> animationSequences = new List<AnimationSequence>(); public List<AnimationSequence> animationSequences = new List<AnimationSequence>();
@ -37,13 +53,12 @@ public class SpriteAnimator : MonoBehaviour
[Tooltip("用于显示动画的SpriteRenderer")] [Tooltip("用于显示动画的SpriteRenderer")]
public SpriteRenderer spriteRenderer; public SpriteRenderer spriteRenderer;
[Header("当前动画编号")] [Header("组循环设置")]
[Tooltip("当前播放的动画编号")] [Tooltip("选择动画组的循环类型")]
public int currentAnimationIndex = 0; public GroupLoopType groupLoopType = GroupLoopType.Forever;
[Header("循环类型")] [Tooltip("动画组循环次数(仅当 GroupLoopType 为 Count 时生效)")]
[Tooltip("选择动画的循环类型")] public int groupLoopCount = 1;
public LoopType loopType = LoopType.Loop;
// 内部变量 // 内部变量
private Dictionary<int, AnimationSequence> animationDictionary = new Dictionary<int, AnimationSequence>(); private Dictionary<int, AnimationSequence> animationDictionary = new Dictionary<int, AnimationSequence>();
@ -51,7 +66,9 @@ public class SpriteAnimator : MonoBehaviour
private int currentFrameIndex = 0; private int currentFrameIndex = 0;
private float frameTimer = 0f; private float frameTimer = 0f;
private bool isPlaying = true; private bool isPlaying = true;
private bool pingPongForward = true; private int currentAnimationIndex = 0; // 当前播放的动画序列索引
private int currentGroupLoopIteration = 0; // 当前动画组已循环次数
private int currentSequenceLoopIteration = 0; // 当前动画序列已循环次数
/// <summary> /// <summary>
/// 初始化动画缓存。 /// 初始化动画缓存。
@ -109,11 +126,45 @@ public class SpriteAnimator : MonoBehaviour
if (!isPlaying || currentAnimation == null || currentAnimation.sprites.Count == 0) if (!isPlaying || currentAnimation == null || currentAnimation.sprites.Count == 0)
return; return;
// 更新帧计时器
frameTimer -= Time.deltaTime; frameTimer -= Time.deltaTime;
if (frameTimer <= 0f) if (frameTimer <= 0f)
{ {
AdvanceFrame(); AdvanceFrame();
// 获取当前动画序列的循环类型
MyLoopType currentLoopType = currentAnimation.loopType;
switch (currentLoopType)
{
case MyLoopType.Once:
if (currentFrameIndex == currentAnimation.sprites.Count - 1)
{
MoveToNextSequence();
}
break;
case MyLoopType.Count:
if (currentFrameIndex == currentAnimation.sprites.Count - 1)
{
currentSequenceLoopIteration++;
if (currentSequenceLoopIteration >= currentAnimation.loopCount)
{
MoveToNextSequence();
}
else
{
ResetCurrentSequence();
}
}
break;
case MyLoopType.Forever:
// 无需特殊处理,继续循环
break;
}
frameTimer = currentAnimation.frameTime; frameTimer = currentAnimation.frameTime;
} }
} }
@ -128,8 +179,8 @@ public class SpriteAnimator : MonoBehaviour
{ {
currentAnimation = selectedAnimation; currentAnimation = selectedAnimation;
currentFrameIndex = 0; currentFrameIndex = 0;
pingPongForward = true;
frameTimer = currentAnimation.frameTime; frameTimer = currentAnimation.frameTime;
currentSequenceLoopIteration = 0;
if (currentAnimation.sprites.Count > 0) if (currentAnimation.sprites.Count > 0)
{ {
@ -158,53 +209,76 @@ public class SpriteAnimator : MonoBehaviour
// 确保当前帧显示正确 // 确保当前帧显示正确
spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex]; spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex];
frameTimer = currentAnimation.frameTime; frameTimer = currentAnimation.frameTime;
// 不重置 currentSequenceLoopIteration以免影响循环次数控制
} }
} }
/// <summary> /// <summary>
/// 前进到下一帧或根据循环类型处理帧索引 /// 前进到下一帧并更新SpriteRenderer的精灵
/// </summary> /// </summary>
private void AdvanceFrame() private void AdvanceFrame()
{ {
switch (loopType) if (currentAnimation.sprites.Count == 0)
return;
currentFrameIndex++;
if (currentFrameIndex >= currentAnimation.sprites.Count)
{ {
case LoopType.Loop: currentFrameIndex = currentAnimation.sprites.Count - 1;
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; // 动画播放完毕后停止
}
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]; spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex];
} }
/// <summary>
/// 重置当前动画序列的播放状态,以便重新循环。
/// </summary>
private void ResetCurrentSequence()
{
currentFrameIndex = 0;
frameTimer = currentAnimation.frameTime;
spriteRenderer.sprite = currentAnimation.sprites[currentFrameIndex];
}
/// <summary>
/// 切换到下一个动画序列,并根据组循环类型决定是否继续循环或销毁动画组。
/// </summary>
private void MoveToNextSequence()
{
currentAnimationIndex++;
if (currentAnimationIndex >= animationSequences.Count)
{
// 完整播放了一遍动画组
currentAnimationIndex = 0;
currentGroupLoopIteration++;
switch (groupLoopType)
{
case GroupLoopType.Once:
isPlaying = false;
Destroy(gameObject); // 销毁动画组
return;
case GroupLoopType.Count:
if (currentGroupLoopIteration >= groupLoopCount)
{
isPlaying = false;
Destroy(gameObject); // 销毁动画组
return;
}
break;
case GroupLoopType.Forever:
// 无限循环,继续播放
break;
}
}
SetAnimation(currentAnimationIndex);
}
/// <summary> /// <summary>
/// 在销毁对象时清理缓存。 /// 在销毁对象时清理缓存。
/// </summary> /// </summary>