Unity代码实现序列帧动画播放器

序列帧动画经常用到,最直接的方式就是用Animation录制。但某些情况下这种方式并不是太友好,需要靠代码的方式进行序列帧动画的实现。

代码实现序列帧动画,基本的思路是定义一个序列帧的数组/列表,根据时间的流逝来确定使用哪一帧并更新显示。

NGUI的UI2DSpriteAnimation已经实现了此功能,但是它支持的目标只有Native2D的SpriteRenderer组件或者NGUI自身的UI2DSprite组件,并不支持UGUI的Image组件。

当然可以通过改写源码的方式来添加对Image组件的支持,不过秉着学习的目的,我这里重新写了一个同时支持Image组件和SpriteRenderer组件的序列帧动画播放器。

代码如下,注释写的很详细了,不再赘述。

using UnityEngine;
using UnityEngine.UI;
using System;

/// <summary>
/// 序列帧动画播放器
/// 支持UGUI的Image和Unity2D的SpriteRenderer
/// </summary>
public class FrameAnimator : MonoBehaviour
{
 /// <summary>
 /// 序列帧
 /// </summary>
 public Sprite[] Frames{ get { return frames; } set { frames = value; } }

 [SerializeField]private Sprite[] frames = null;

 /// <summary>
 /// 帧率,为正时正向播放,为负时反向播放
 /// </summary>
 public float Framerate { get { return framerate; } set { framerate = value; } }

 [SerializeField] private float framerate = 20.0f;

 /// <summary>
 /// 是否忽略timeScale
 /// </summary>
 public bool IgnoreTimeScale{ get { return ignoreTimeScale; } set { ignoreTimeScale = value; } }

 [SerializeField]private bool ignoreTimeScale = true;

 /// <summary>
 /// 是否循环
 /// </summary>
 public bool Loop{ get { return loop; } set { loop = value; } }

 [SerializeField]private bool loop = true;

 //动画曲线
 [SerializeField]private AnimationCurve curve = new AnimationCurve (new Keyframe (0, 1, 0, 0), new Keyframe (1, 1, 0, 0));

 /// <summary>
 /// 结束事件
 /// 在每次播放完一个周期时触发
 /// 在循环模式下触发此事件时,当前帧不一定为结束帧
 /// </summary>
 public event Action FinishEvent;

 //目标Image组件
 private Image image;
 //目标SpriteRenderer组件
 private SpriteRenderer spriteRenderer;
 //当前帧索引
 private int currentFrameIndex = 0;
 //下一次更新时间
 private float timer = 0.0f;
 //当前帧率,通过曲线计算而来
 private float currentFramerate = 20.0f;

 /// <summary>
 /// 重设动画
 /// </summary>
 public void Reset ()
 {
 currentFrameIndex = framerate < 0 ? frames.Length - 1 : 0;
 }

 /// <summary>
 /// 从停止的位置播放动画
 /// </summary>
 public void Play ()
 {
 this.enabled = true;
 }

 /// <summary>
 /// 暂停动画
 /// </summary>
 public void Pause ()
 {
 this.enabled = false;
 }

 /// <summary>
 /// 停止动画,将位置设为初始位置
 /// </summary>
 public void Stop ()
 {
 Pause ();
 Reset ();
 }

 //自动开启动画
 void Start ()
 {
 image = this.GetComponent<Image> ();
 spriteRenderer = this.GetComponent<SpriteRenderer> ();
 #if UNITY_EDITOR
 if (image == null && spriteRenderer == null) {
 Debug.LogWarning ("No available component found. 'Image' or 'SpriteRenderer' required.", this.gameObject);
 }
 #endif
 }

 void Update ()
 {
 //帧数据无效,禁用脚本
 if (frames == null || frames.Length == 0) {
 this.enabled = false;
 } else {
 //从曲线值计算当前帧率
 float curveValue = curve.Evaluate ((float)currentFrameIndex / frames.Length);
 float curvedFramerate = curveValue * framerate;
 //帧率有效
 if (curvedFramerate != 0) {
 //获取当前时间
 float time = ignoreTimeScale ? Time.unscaledTime : Time.time;
 //计算帧间隔时间
 float interval = Mathf.Abs (1.0f / curvedFramerate);
 //满足更新条件,执行更新操作
 if (time - timer > interval) {
  //执行更新操作
  DoUpdate ();
 }
 }
 #if UNITY_EDITOR
 else {
 Debug.LogWarning ("Framerate got '0' value, animation stopped.");
 }
 #endif
 }
 }

 //具体更新操作
 private void DoUpdate ()
 {
 //计算新的索引
 int nextIndex = currentFrameIndex + (int)Mathf.Sign (currentFramerate);
 //索引越界,表示已经到结束帧
 if (nextIndex < 0 || nextIndex >= frames.Length) {
 //广播事件
 if (FinishEvent != null) {
 FinishEvent ();
 }
 //非循环模式,禁用脚本
 if (loop == false) {
 currentFrameIndex = Mathf.Clamp (currentFrameIndex, 0, frames.Length - 1);
 this.enabled = false;
 return;
 }
 }
 //钳制索引
 currentFrameIndex = nextIndex % frames.Length;
 //更新图片
 if (image != null) {
 image.sprite = frames [currentFrameIndex];
 } else if (spriteRenderer != null) {
 spriteRenderer.sprite = frames [currentFrameIndex];
 }
 //设置计时器为当前时间
 timer = ignoreTimeScale ? Time.unscaledTime : Time.time;
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 在Unity中实现动画的正反播放代码

    using UnityEngine; using System.Collections; public class AnimationAntiSowing : MonoBehaviour { public static AnimationAntiSowing _initialise; void Awake() { _initialise = this; } /// <summary> /// 动画进行正反播放 /// </summary> /// <param name=&q

  • Unity实现卡拉OK歌词过渡效果

    好长时间之前做过的一个项目 , 其中设计到用Unity模拟卡拉OK歌词过渡的效果 , 如下图所示 ↓ , 这里简单把原理部分分享一下. 文章目录 演示效果 ↓ 歌词效果类 ↓ 配套资源下载 演示效果 ↓ 实现歌词动态调整功能 实现动态读取歌词文件功能 实现歌曲快进快退功能 实现歌曲单字时间匹配功能 实现可动态更换歌词前景色背景色功能 注: 这里为实现精准过渡效果使用的是KSC歌词文件, 并不是LRC文件哦 . 这其中我认为就是如何实现歌词部分的前景色向后景色过渡的效果了, 开始的时候我想的也是很

  • Unity调取移动端的麦克风进行录音并播放

    本文实例为大家分享了Unity调取移动端的麦克风进行录音并播放的具体代码,供大家参考,具体内容如下 1.对MicroPhone类的理解 对麦克风的调用在Unity里主要是用到了MicroPhone这个类,此类里面有几个方法可以方便我们实现功能 2.代码演示 #region 模块信息 // ********************************************************************** // Copyright (C) 2018 Blazors // P

  • Unity3D实现播放gif图功能

    Unity是不识别Gif格式图的,需要我们使用c#将gif里多帧图转化为Texture2D格式.需要使用System.Drawing.dll.此dll在unity安装目录下就可以找到.由于unity没有gif格式的文件,所以我们无法在面板指定,需要动态加载.所以将gif图放在StreamingAssets文件夹下.以下为源代码: using System; using System.Collections; using System.Collections.Generic; using Syst

  • Unity代码实现序列帧动画播放器

    序列帧动画经常用到,最直接的方式就是用Animation录制.但某些情况下这种方式并不是太友好,需要靠代码的方式进行序列帧动画的实现. 代码实现序列帧动画,基本的思路是定义一个序列帧的数组/列表,根据时间的流逝来确定使用哪一帧并更新显示. NGUI的UI2DSpriteAnimation已经实现了此功能,但是它支持的目标只有Native2D的SpriteRenderer组件或者NGUI自身的UI2DSprite组件,并不支持UGUI的Image组件. 当然可以通过改写源码的方式来添加对Image

  • Unity Shader实现序列帧动画效果

    本文实例为大家分享了Unity Shader序列帧动画效果的具体代码,供大家参考,具体内容如下   实现原理 主要的思想是设置显示UV纹理的大小,并逐帧修改图片的UV坐标.(可分为以下四步) 1.我们首先把 _Time.y 和速度属性_Speed 相乘来得到模拟的时间,并使用CG 的floor 函数对结果值取整来得到整数时间time 2.然后,我们使用time 除以_HorizontalAmount 的结果值的商来作为当前对应的行索引,除法结果的余数则是列索引. 3.接下来,我们需要使用行列索引

  • Android媒体开发之音乐播放器

    本文实例为大家分享了Android媒体开发之音乐播放器的具体代码,供大家参考,具体内容如下 可以对音乐文件实现播放.暂停.重播和停止功能.退出应用和回到桌面时音乐停止. 主界面: 主界面配置文件mian.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" andro

  • js实现的万能flv网页播放器代码

    本文实例讲述了js实现的万能flv网页播放器代码.分享给大家供大家参考,具体如下: <div id="player5"><script type="text/javascript" src="swfobject.js"></script><script type="text/javascript"> var s5 = new SWFObject("FlvPlayer20

  • 实现音乐播放器的代码(html5+css3+jquery)

    看下面的效果图很不错吧,是怎么实现的呢?下面小编给大家分享下我的一番宝物,Lisa唱的 在angel beats的插曲.用到html5.css.jquery实现此音乐播放器. 一番宝物,Lisa唱的   在angel beats的插曲 最后在简述这个东西怎么写之前,本人男,24岁,籍贯上海,诚招女友一枚,要求:性格温顺...(省略500字) <div class="Music"> <div class="MusicPlaySound"> &l

  • JS模拟酷狗音乐播放器收缩折叠关闭效果代码

    本文实例讲述了JS模拟酷狗音乐播放器收缩折叠关闭效果代码.分享给大家供大家参考,具体如下: 这是一款模拟酷狗音乐播放器的关闭特效,采用JavaScript实现,关闭的时候播放界面缩成一条线,然后消失,就像有些电视机突然停电的效果,很有意思的网页动画特效. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-kugou-music-player-style-demo/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3

  • 原生JS实现音乐播放器的示例代码

    本文主要介绍了原生JS实现音乐播放器的示例代码,分享给大家,具体如下: 效果图 音乐播放器 播放控制 播放进度条控制 歌词显示及高亮 播放模式设置 播放器属性归类 按照播放器的功能划分,对播放器的属性和DOM元素归类,实现同一功能的元素和属性保存在同一对象中,便于管理和操作 const control = { //存放播放器控制 play: document.querySelector('#myplay'), ... index: 2,//当前播放歌曲序号 ... } const audioFi

  • 基于Qt实现简易GIF播放器的示例代码

    目录 一.项目介绍 二.项目基本配置 三.UI界面设计 四.主程序实现 4.1 mainwindow.h头文件 4.2 mainwindow.cpp源文件 五.效果演示 一.项目介绍 利用Qt设计一个简易GIF播放器,可以播放GIF动画.其基本功能有载入文件.播放.暂停.停止.快进和快退. 二.项目基本配置 新建一个Qt案例,项目名称为“GIFTest”,基类选择“QMainWindow”,创建UI界面复选框的选中状态,完成项目创建. 三.UI界面设计 UI界面如下: 界面中创建了8个控件,其名

  • 网上比较常用的嵌入网页中的播放器代码收藏

    例如:网络上最流行的windows media流(asf,wma,wmv格式...),Real流(rm,rmvb...),还有MPEG系列编码格式(MP4/MP3格式...) Windows Media Video 是微软推出的一种流媒体格式,它是在"同门"的ASF(Advanced Stream Format)格式升级延伸来得.在同等视频质量下,WMV格式的体积非常小,因此很适合在网上播放和传输.Windows Media Player9兼容所有格式的WMV,官方编码器是Window

  • 宝丽通3.90播放器调用代码

    随着版本的不断更新,软件更加成熟了,现在终于支持ActiveX皮肤了. *Update:3.90增加片头片尾广告功能. 复制代码 代码如下: <OBJECT ID="ActiveX" name="player" CLASSID="CLSID:C3D8F2C7-A508-4724-BC3A-C247058D17EB" width=400 height=360 VIEWASTEXT> <param name="url&qu

随机推荐