拖尾探索

拖尾探索

标签(空格分隔): 特效


拖尾效果

个人理解是一个物体在移动的时候,在它的移动路径中经过的位置会出现残影、尘埃等等特效的一种效果。如汽车移动时排放的尾气就是一种拖尾效果,可以用拖尾加粒子系统组合来完成。

unity 里面的拖尾

unity 中实现拖尾非常简单,给 gameobject 添加一个 TrialRenderer 就完事了,丰富的 API 和参数几乎可以解决拖尾的所有问题。因为 unity 没有开源,我们尝试从他的接口去猜测他的实现原理。

重要 API

Time:
- 拖尾存在的时间。

Min Vertex Distance:
- 最小顶点距离,这个距离决定了一个物体至少需要移动多少的距离,才会显示出拖尾。注意这个值越小,意味着拖尾的分段渲染更多,效果越平滑,同时性能方面也会有更多的消耗。所以应该尽可能地在不影响需求效果的情况下使用最大的值。

Width:
- 拖尾的宽度,在 unity 中,width 属性可以设成一条曲线,作为对应比例的长度的尾巴的宽度。

TrialRenderer 还有很多很好用的 API 但是最关键的应该就是这几个了,从上面几个 API 看来,unity 的做法是,按照这个 Min Vertex Distance 来将尾巴划分成很多段,每一段有对应的顶点数据逐段渲染的。在游戏蛮牛中也又看到使用 MeshRenderer 来实现武器拖尾效果的方法,原理就是在每帧记录当前帧的武器位置、朝向信息、并根据效果持续时间来记录消失时间点。详情

总结下来,unity 上对拖尾的支持可以说是比较完备的,而且容易使用,当然没有源码的情况下,它屏蔽的细节也相当的多不方便去探索背后的实现原理。

2D 引擎的拖尾

cocos

2D 的拖尾效果在搜索引擎中最容易搜出来的就是 cocos 的拖尾,cocos 的拖尾和 unity 一样也是有一个专门的类 CCMotionStreak 以供使用。博主火云洞红孩儿也进行了相关的源码解读。里面的原理也是和上面说的类似,根据设定的最小段值,来记录物体移动的一系列顶点,再根据顶点来生成四边形,最后达到拖尾效果。

egret & laya

相比于 cocos ,egret 和 laya 这两个 h5 引擎是没有提供像 CCMotionStreak 这种专门的拖尾类型的,这时如果想实现拖尾效果,我们只能够通过自己来实现了。在经过一番搜索和思考之后,发现有几种形式的拖尾是在 h5 引擎上可行性比较高的。

  1. 使用一个在一定范围不断发射粒子的粒子系统,通过移动发射器的位置,让发射出去的粒子成为“拖尾”。
  2. 直接在物体移动过的位置后生成透明度不同的图片,造成残像的“拖尾”。参考
  3. 使用更加简单的“画线”法,来模拟拖尾。参考

laya 拖尾参考实现

这里是暂时只实现了第一种移动粒子发射器的方法,本来这种最简单的方法没什么说的必要,但是因为在 Laya 上粒子发射器的位置隐藏的有点深,所以就写出来分享一下。

在白鹭引擎里,粒子发射器的位置比较明确,有一个 emitterXY 的公开接口可以设置,不过在 Laya 的实现中,就没有这么明确了。在 Laya 的粒子系统中,Particle2D 是负责播放粒子效果的类型,里面有一个 EmitterBase 粒子发射器的类型引用 emitter,和一个粒子参数数据类型 ParticleSetting 的引用。复杂就复杂在于,emitter 中并没有控制粒子发射位置的接口。

继续查源码会发现 emitter 发射粒子的函数 emit() 最后其实是调用 ParticleTemplate.addParticleArray(positon: Float32Array, velocity: Float32Array) 方法。毫无疑问,里面的第一个参数 position 就是粒子发射的位置。这里遇到的问题是我把 Emitter 里面传入作为 position 的变量 _posRange 当成了最终的位置,殊不知,其实在 ParticleTemplate 类型中,其实是有几重的继承关系的。其中,真正创建粒子的是 ParticleTempleWebGL 这一层的 addParticleArray 方法中调用 ParticleData.Create(settings:ParticleSetting, position:Float32Array, velocity:Float32Array, time:Number) 中的 position 才是最终的发射位置。而在 Emitter 中传入的 position 其实在 ParticleTemplateWebGL 的子类 ParticleTemplate2D 里面还会经过处理,查看 ParticleTemplate2DaddParticleArray 方法可以发现,里面加上的 ParticleTemplate2D 的字段 xy 才是真正的控制粒子发射位置,_posRange 不过是一个发射的误差半径。

理解到了这里,问题就很简单了,简单写一下代码

private sp:Particle2D = new Particle2D(settings);

onMouseMove():void{
    (this.sp.emitter.particleTemplate as Laya.ParticleTemplate2D).x = Laya.stage.MouseX;
    (this.sp.emitter.particleTemplate as Laya.ParticleTemplate2D).y = Laya.stage.MouseY;
    this.sp.emit();
}

区别

unity 和 cocos 的拖尾能够做出的拖尾效果是像刀剑划过的光影那种拖尾,而不是单纯的有东西渐隐显示出移动轨迹的拖尾。是像这样的,而如果加入粒子材质的话,可以做出更加炫酷的效果
unity 拖尾

而针对上面的实现,只能实现像这样的效果
h5 粒子系统拖尾

更好的实现

在参考了 cocos 源代码的拖尾实现后,自己在 Laya 上写了一个拖尾效果,代码是在公司里面写的不方便拿出来,又不想再抄一遍,就在这里把思路说一下。补充一下,原理上和 cocos 上是相似的,逐帧取样点,使用这些样点生成一段段的条带,至于颜色、透明度、宽度渐变这些都是通过插值做出来的

demo

思路:

  1. 逐帧取样路径点,检测该路径点和上一个点之间的距离是否足够远(太小不必生成)。
  2. 遍历路径点数组,不断取当前点和后一个点,计算这两个点对应生成的条带位置、角度、宽高,并存入一个 Data 数组中。
  3. 遍历 Data 数组,创建对应的矩阵,使用 drawtexture 把它画出来。

注意:

  1. 逐帧所取的路径点,有可能因为速度过快,而使两个点之间的距离比较远,这样计算出的条带可能会很长,以至于整个尾巴走样,这种情况可以创建多一个顶点数组 vertex[],将路径点遍历一遍,并划分成足够小的点再存进顶点数组 vertex[],然后在第 2 步中使用 vertex[] 代替计算即可。
  2. 生成条带的数学计算需要自己去完成,我的方法也很笨重。
  3. 结合 laya 的粒子系统和发光滤镜,可以做出非常不错的效果。

缺点:

  1. 在小距离缓慢移动的时候,矩形拼凑特别明显。
  2. 拐角时会有缝隙。

引用

unity - TrailRenderer
游戏蛮牛 - 武器拖尾的实现

更多

unity - 非 TrailRenderer 实现
unity - Animation 实现

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值