创建原因
使用Animator进行序列帧控制的话,播放到指定帧,重新播放这些操作使用起来非常的不方便,所以自己写了一个序列帧播放的脚本。
一、主要功能
1、播放,从指定帧播放
public void Play()
{
Play(0);
}
public void Play(int startFrame)
{
currentFrame = startFrame;
spriteLoader.sprite = allAnimationTextures[startFrame];
isPlaying = true;
}
2、跳转到指定帧
public void Skip(int frame,bool isPause = false)
{
currentFrame = frame;
spriteLoader.sprite = allAnimationTextures[frame];
if (isPause)
{
Pause();
}
}
3、暂停 和 停止
public void Pause()
{
isPlaying = false;
}
public void Stop(bool isClear = false)
{
currentFrame = allAnimationTextures.Count-1;
if (isClear)
{
spriteLoader.sprite = null;
}
else
{
spriteLoader.sprite = allAnimationTextures[currentFrame];
}
Pause();
}
4、播放完成回调
public void OnComplete(Action action)
{
onComplete += action;
}
二、代码
// ========================================================
// Description:2D动画播放器
// Author:MDC
// Creat Time:2022-09-29 22:18:00
// Tips:针对Animator对2D动画控制不方便而创建,方便进行跳转、暂停、播放、完成回调等操作。
// ========================================================
using System;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(SpriteRenderer))]
public class AnimationPlayer : MonoBehaviour
{
[Header("循环播放")]
public bool isLoop = false;
[Header("启动时播放")]
public bool awakePlay = false;
[Header("播放帧率1-120")]
[Range(1,120)]
public int frameRate = 25;
public float time //动画时长
{
get {
return allAnimationTextures.Count / frameRate; }
}
public int CurrentFrame
{
get {
return currentFrame; }
}
public bool IsPlaying
{
get {
return isPlaying; }
}
[SerializeField]
private List<Sprite> allAnimationTextures; //所有动画贴图
private int currentFrame = 0; //当前帧
private bool isPlaying = false; //是否正在播放
private Action onComplete; //播放完成事件
private SpriteRenderer spriteLoader; //图片加载器
private float timer; //计时器
private void Awake()
{
spriteLoader = GetComponent<SpriteRenderer>();
if (awakePlay)
{
isPlaying = true;
}
}
void Start()
{
}
void Update()
{
SlidePlay();
}
private void SlidePlay()
{
timer+=Time.deltaTime;
if (timer < 1f/ frameRate)
{
return;
}
timer = 0;
if (isPlaying)
{
if (currentFrame == allAnimationTextures.Count)
{
if (isLoop)
{
currentFrame = 0;
}
else
{
isPlaying = false;
if (onComplete != null)
{
onComplete.Invoke();
onComplete = null;
}
return;
}
}
spriteLoader.sprite = allAnimationTextures[currentFrame];
currentFrame++;
}
}
public void Play()
{
Play(0);
}
/// <summary>
/// 从第startFrame开始播放
/// </summary>
/// <param name="startFrame"></param>
public void Play(int startFrame)
{
currentFrame = startFrame;
spriteLoader.sprite = allAnimationTextures[startFrame];
isPlaying = true;
}
/// <summary>
/// 跳转到指定帧,isPause为true时跳转后暂停
/// </summary>
/// <param name="frame"></param>
/// <param name="isPause"></param>
public void Skip(int frame,bool isPause = false)
{
currentFrame = frame;
spriteLoader.sprite = allAnimationTextures[frame];
if (isPause)
{
Pause();
}
}
/// <summary>
/// 暂停播放
/// </summary>
public void Pause()
{
isPlaying = false;
}
/// <summary>
/// 停止播放,isClear为true时清除画面
/// </summary>
/// <param name="isClear"></param>
public void Stop(bool isClear = false)
{
currentFrame = allAnimationTextures.Count-1;
if (isClear)
{
spriteLoader.sprite = null;
}
else
{
spriteLoader.sprite = allAnimationTextures[currentFrame];
}
Pause();
}
/// <summary>
/// 播放完成回调
/// </summary>
/// <param name="action"></param>
public void OnComplete(Action action)
{
onComplete += action;
}
}
实际上除了播放完成触发事件之外我还做了一个扩展版,包含 指定帧触发事件 和 循环情况下一遍播放完成后触发事件,但是因为怀疑可能会存在bug给大家带来困扰所以并未粘贴,扩展版大家可以点击这里下载查看,有兴趣的可以私聊沟通。