接着上一篇博客进行介绍,当我们得知我们能够控制一个粒子(Particle)的多种属性和动作播放后,我们需要做的就是开始构建:
序列帧动画系统。
根据起初设计我认为其中有三个比较关键的类:
SpriteAnimationSystem 所有的序列帧动画系统的管理类
AnimationSprite 包装好的粒子(用来管理和维护粒子系统释放出的单个粒子)
SpriteCreator 包装好的粒子系统(用来维护单个粒子系统,同时内部会维护所有粒子的变化,类似于一个总管)
这样基本就包含了全部的粒子系统功能。
其余的实现方式应该会跟各自的具体需求不同而不同,接下来我会主要针对性的介绍一些在制作过程中遇到的问题:
(一)序列帧动画的播放与生命周期的具体关系
我们之前谈论过,粒子的序列帧动画播放是粒子的生命周期控制的,那么我们一定要知道具体的生命周期与所播放帧的具体关系,这样才能保证我们在播放动画的时候不会出现跳帧、错帧、抖动偏移等问题。
那么具体这其中的具体关系是什么呢?我依旧选择了根据实验来检测:
按照两者是线性的关系来看,那有以下几种可能性——
1* 当前生命周期向上取整获取当前帧
0 1 2 3 —— 当前帧数(0开始)
|---|---|---| —— 总时长
3 2 1 0 —— remainingLifeTime
2* 当前生命周期向下取整获取当前帧
0 1 2 3 —— 当前帧数(0开始)
|---|---|---| —— 总时长
3 2 1 0 —— remainingLifeTime
3*当前生命周期round方式整获取当前帧
0 1 2 3 —— 当前帧数(0开始)
|---|---|---| —— 总时长
3 2 1 0 —— remainingLifeTime
根据上图三种形式,测试得到粒子系统是按照第 3 种方式实现的,所以当我们需要播放某一时间段的序列帧动画时,我们需要按照这个实现方式来处理相关的序列帧播放,否则会出现各种各样奇怪的帧数混乱问题。
(二)粒子系统中粒子数组的动态维护
这个问题出现在动态增删粒子的时候。粒子系统中,粒子都是通过一个粒子数组的形式存储维护。粒子(Particle)是结构体,属于值对象,且粒子系统仅仅提供了SetParticles的方法来设置整个数组。
同时我们关于粒子系统的动态设置是非常频繁的,例如生命周期设置,位置设置等等,所以我们需要维护的,一定是数组而非列表,否则每次都需要进行列表和数组的转换,这种转换消耗非常大。
确定了要维护数组那么就又有了一个问题——数组的动态扩容和增删。
这里我比较推荐设置一个具体的粒子总数变量来记录粒子数组长度。
然后根据这个值结合自身需求设置扩容值,然后通过设置粒子清空,来表示已经移除的粒子,这样就可以动态维护粒子数组,同时也能最大的减少性能消耗,当然如果有更好的方法来动态维护数组,也可以采用更好的方式。
(三)使用同种材质和shader,实现不同的颜色遮罩效果
这里与shader实现有关,具体实现可以通过下面链接的文章,来实现。
https://blog.csdn.net/shenmifangke/article/details/51524812
(四)大小不同的序列帧的大小统一规则
这里的问题是比较难以发现和难以处理的。当导入大小不同的精灵进入一个粒子系统中时,粒子系统是如何统一和设置粒子的大小的呢?
最开始遇到的问题是:为什么精灵原始的大小都是一样的,当放入不同的粒子系统会发现精灵被拉伸了。
因此又做了以下的实验来探究粒子系统的大小统一规则:
1*所有的精灵都统一与第一个精灵采取同样的缩放比例
2*所有的精灵都统一与最后一个精灵采取同样的缩放比例
3*所有的精灵都采用所有精灵的本身缩放比例
因为每个精灵裁切后的比例缩放都不一样,所以第三种是不可能的统一规则,根据实验,将同样的精灵分段进行导入,实验得出粒子系统采用的是第一种统一规则。
得到这个结论后,那我们如果需要让粒子还原到原图本身的大小,那就按照第一个精灵的缩放比例等比还原就好了!