Unity自定义序列帧播放器


创建原因

使用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给大家带来困扰所以并未粘贴,扩展版大家可以点击这里下载查看,有兴趣的可以私聊沟通。

猜你喜欢

转载自blog.csdn.net/qq_27050589/article/details/127154494