搜索
热搜: 活动 交友 discuz
查看: 4801|回复: 24

[教程] 【挖坑】粒子特效教程

[复制链接]

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
发表于 2017-11-13 07:20:13 | 显示全部楼层 |阅读模式

前方高能预警!非战斗人员请尽快登录!

您需要 登录 才可以下载或查看,没有帐号?注册账号

x
本帖最后由 Greg 于 2018-1-28 14:04 编辑

算起来加入amhc已经很久了…这么长时间里除了做了一点点翻译以外,一直没产生什么贡献值,所以总想着做点什么力所能及的事情。正好发现很多人都对粒子系统抱有兴趣,奈何教程和资源太少,难以研究这个强大的工具。因此我打算开这个坑来发一篇教程,和大家分享一下对粒子编辑器的一点点理解。预计我会写的很慢很慢,而且会不定时鸽一阵子,毕竟还要上学考试…见谅

第一写这种教程,肯定很粗糙,如果有说得不准确的地方请各位务必指正。
(另:我有想过做视频教程,因为粒子这种涉及到动画的东西靠gif和图片确实有点难讲清楚,如果各位觉得看图文实在是难以理解的话,请告诉我
每一楼的内容有字数限制,也就是说我要用很多很多楼才能写完这个教程(实在是不会用这个论坛啊…),所以请各位暂时不要回复此贴,有问题请私信,谢谢

注明:1.27 第二章 - 动态系统已更新


那么正文如下
——————————————————————分割线——————————————————————————————————

粒子编辑器教程
其实我本来想把教程写成两部分,一部分相当于“速成”教程,只将一下怎么操作编辑器自带的特效,另一部分讲的仔细一点,会分析到很多深层一点的东西。但是转念一想,所谓速成其实不是一个很好的学习态度,况且不懂原理的话,还是会遇到很多很多难以解决的问题。所以我打算只写第二部分,砍掉了速成的部分。

暂定的目录如下:

第一章:认识基本工作原理
第二章:静态系统
第三章:动态系统

为什么要把第二第三章分成动态和静态呢?因为我认为这是“初级”和“高级”水平的重要分水岭。静态系统的意思是,在粒子被生成之后,它就不再接受外界的控制因素了,只会沿着我们设定好的轨迹走。而动态则相反,我们能够全程控制粒子的特征,从出生到结束。随着教程进行我们就会发现,动态和静态系统所用到的“方法”是很不一样的,他们所依赖的基本思路也是不一样的。

第一章:
1.1第一句话
有一句话要写在最前面:什么是“粒子(Particle?)”?
粒子是图片,是图片,是图片!请务必记住和理解这个概念,粒子不是什么颗粒或者玄乎的东西,99%的情况下,它是一张图!

1.2 粒子类型
带着前面提到的“图片”概念,我们来看下面这张图,它包含了所有你能渲染的粒子“类型”。

renderer.png
绝大多数情况下,我们只会用到下面几项:
Render blobs
Render deferred light
Render models
Render projected
Render rope
Render screen shake
Render sprite trail
Render sprites(最普遍的类型)
在本教程中,也只会涉及到我列出来的这几项常用类型。那么我们如何用“图片”的概念来理解这些粒子类型呢?
一句话:类型决定了图片的“行为”。具体解释如下:
Sprite:每张图片都是一个独立的个体。
Rope:每张新产生的图片,都会和上一张连在一起,组成一“长条”图片,就像绳子一样。
Sprite trail: 每张图片都是一个独立的个体,但是身后会拖着一条“轨迹”(尾巴)。
Projected: 一张图被投影(project)到地面上。
剩下三项比较特殊,Model/blob/screenshake并不能称之为“图片”,但是只要你理解了上面四个概念,你自然也能理解这三项的工作方式。如果你暂时不能理解,也没有关系,后面会有大量的例子让你理解这些概念。

1.2 粒子的基本属性
接下来我们来看,哪些参数具体规范了图片的“行为”。下图为Sprite的各项属性:

sprite_property.png
红圈里是一个粒子系统最重要的属性之一:Texture. Texture决定了我们要把什么图放上去。像图里默认的Texture就是一个白色的圈,我们可以把它改成任何我们想要的东西,比如花瓣,比如树叶,甚至可以加入我们自己设计的图案。请记住,这不是一张静态的图片,它可以是一张动图。在此时我们还不需要它自己动起来,但是请千万不要认为,这只是一张不会动的图片。
除了Texture以外,图中还有很多很多功能强大的属性,但是为了让教程变的流畅一些,我们把对它们的介绍放到后面。

1.4.1 粒子初始化。
当我们完成了对Texture的设定之后,我们已经确定了要把哪张图片放到屏幕上。接下来我们就要完成“放”这个动作。请将“放”这个动作想象成这样两步:
1、你手里攥着一张图,伸出胳膊,把它举到指定的一个点上;
2、松手,让它随风而去。
可以说,一切粒子都是这样工作的,只是以一种更抽象的方式。步骤1代表了“初始化”,步骤二代表了“操作”,也就是Initializer和Operator。正确的描述应该是,所有的粒子都是这样工作的:第一步,完成初始化(比如放到一个指定的位置);第二步,开始运行(比如被风吹散)。如果你不能理解为什么要分成两步,或者是觉得完全可以一步到位,那么请你暂时说服你自己,因为后面你会慢慢地理解,这是一种多么方便的工作方式。

现在我们可以打开粒子编辑器,接下来就要讲解第一个例子了。点击左上角File->New 新建一个空的粒子文件, 然后保存。任何时候你新建一个粒子文件,第一件事就是保存!我已经记不清多少次因为没保存而丢掉做好的粒子了。请记住保存这个良好的习惯。

example1.gif
假设我们要做上面图里的这个特效,我们应该这样初始化我们的粒子:
1. 让粒子在原点生成
2. 给粒子一个速度,让粒子向斜上方飞。
initializer_1.png

对应到Initializer里也就是这两个东西。请看他们的具体数值。
init_3.png init_2.png
右边的Velocity Random:
变成蓝色的两项,是我们唯一改动过的地方。这非常好理解,在粒子被生成的时候,我们在(-50,-50,200)(50,50,200)之间随机出一个速度,然后让粒子按照这个速度飞。

左边的Position within sphere random(图上没显示全)。顾名思义,这个initializer会        在一个sphere里随机一个位置给粒子。既然我们需要粒子在原点出生,那就只需要把球体的半径设为0,也就是保持默认。

其实图上除了两个InitializerRender sprites以外还有两项——Movement basic Emit continuously. 后者很好理解,只是持续发射粒子而已。前者是个有点奇怪的东西,它的功能主要是“让粒子动起来”。也就是说,如果没有这一项,即便我们设置了速度,粒子也是不会动的(所以很多人一开始都很莫名其妙,为什么自己的粒子不会动)。它还有其他的一些功能,我们后面会提到。
这五项参数就足以达到图里的效果了。但是这还远远不够。只要过个十秒钟我们就会发现,粒子突然停下来了。
stopped.png
稍加观察可以发现,窗口顶部有一个1000/1000——这表示这个系统“满了”,所以粒子的生成被迫停止了。解决这个问题也很简单,我们只需加上两项参数:1Lifetime random, 设定粒子的生命周期;2Lifespan decay,让粒子的生命结束之后能被删除。稍稍回顾前面“两步走”的概念,可以发现Lifetime random肯定是个initializer,因为这是粒子生成之初就要确定的事;lifespan decay肯定是个operator, 因为删除粒子是在运行过程中删除的。
lifespan.png
如图设置即可。观察一下运行时的粒子数,再也不会超过100了(如果你没有修改发射速度的话)。
请再次思考一下InitializerOperator的概念,想一想它们各自都是干什么的。如果无法理解为什么我们要把这两个东西分开的话,是无法理解粒子系统的运行方式的。

未完待续





评分

参与人数 3荣誉 +1 金币 +200 创造力 +10 求知欲 +10 互助 +20 智慧 +15 节操 -30 收起 理由
Ajustguguit -19 你的节操掉了!
kzhang9 + 100 + 10 + 10 + 10 + 10 -10 很给力!赞!
无双 + 1 + 100 + 10 + 5 -1 很给力!赞!

查看全部评分

回复

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-1-20 08:39:32 | 显示全部楼层
本帖最后由 Greg 于 2018-1-28 14:02 编辑

不知道为什么,最近一次更新的内容突然显示在三楼了。为了不打乱教程顺序,此楼暂时作废。
回复 支持 1 反对 0

使用道具 举报

7

主题

10

帖子

59

积分

Lv:1 隐谧贤者

UID
12756
金币
53
精华
0
节操
0
发表于 2017-12-31 11:39:54 | 显示全部楼层
厉害,我多去看看,有意朝美工和作图发展哟~~
回复 支持 1 反对 0

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2017-11-13 09:13:18 | 显示全部楼层
本帖最后由 Greg 于 2018-1-28 14:03 编辑

1.4.2 更多的Initializer
在1.4.1里我们初步分析了initializer的工作方式,接下来我们来研究更多更强大的initializer. 我会通过不断修改上面那个粒子的方式来介绍一些initializer. 在此之前,请将render sprite 里的Texture设置为“materials/particle/flower/flower.vtex”.
以下是我们要添加的Initializer:
1、Color random
非常直接的名字。基本上我们只会用到color1和color2两项。
2、Alpha random
修改透明度。
3、Radius random
修改粒子(图片)大小
4、Sequence Random
修改粒子的sequence。我之前提到过,我们所说的粒子是“图片”,绝不是指静态的图片,它完全可以是动图,或者是很多张图片。例如我们选取了花瓣的图片,它可以包含数十种不同形状的花瓣。Sequence = 其中的一种形状。Sequence Random这个initializer就是用来选取我们想用的形状。
5、Rotation Random
修改粒子的初始旋转。请记住它只设置粒子的初始角度而非旋转速度。
6、Rotation Speed Random
修改例子的初始旋转速度,这个才是用来设置转速的。
(rotation相关的Initializer均需要在Operator里加入“Rotation Basic”才能生效)
7、Velocity Noise
一个非常有意思的initializer. 我的理解是Noise这个词取自于Perlin Noise算法,产生的是不规律但是也不随机的值。所以它和Velocity Random产生的效果大相径庭。强烈推荐大家在此链接下查阅官方解释,非常容易理解。(https://developer.valvesoftware. ... zers#Velocity_Noise
我只用一张图来表示它的效果 example_noise.gif

以上7个Initialier,如果调教的当的话,已经可以产生很丰富的效果了。我把我做的例子放在下面,大家可以自行尝试不同的参数,获得不同的效果。
example_2.gif
我所用到的所有initializer和operator:
final_list.png

未完待续
回复 支持 反对

使用道具 举报

1

主题

28

帖子

534

积分

Lv:3 空明术士

UID
4214
金币
833
精华
0
节操
-23
QQ
发表于 2017-11-13 15:10:39 | 显示全部楼层
辛苦大大,还有后续吗?
回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2017-11-13 15:33:43 | 显示全部楼层
Gabrielus 发表于 2017-11-13 15:10
辛苦大大,还有后续吗?

有的有的…这才第一天呢…
回复 支持 反对

使用道具 举报

3

主题

35

帖子

428

积分

Lv:3 空明术士

UID
1759
金币
630
精华
0
节操
0
发表于 2017-11-13 17:34:31 | 显示全部楼层
期待整点炫酷的
回复 支持 反对

使用道具 举报

17

主题

253

帖子

1802

积分

魔导师

UID
3373
金币
8028
精华
1
节操
-92

黑科技玩的6创世者隐修议员扛把子教程大师开拓者平妖侠士

发表于 2017-11-19 16:21:16 | 显示全部楼层
我觉得粒子这套东西,真的缺一个蓝图系统。。难用的一B。。
回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2017-11-22 06:58:36 | 显示全部楼层
本帖最后由 Greg 于 2017-11-22 07:09 编辑

更新了更新了…

1.4.3 依然更多的Initializer
1.4.2里我们主要通过一个例子讲解了一些Initializer, 在这一节里我会脱离例子,直接讲一些initializer和他们的参数。
1、Position along ring random
初始位置。粒子的位置将会被设置到“环”上。我们可以修改环的各项属性:radius, thickness, roll/yaw/pitch 都相当直白,我就不做解释了。值得一提的是initial speed两项,这两项会给粒子增加一个基础速度,方向只能是远离环的中心。不过这个真的非常好用。
此外提一下even distribution. 名字很直白,均匀分布,如果你勾上这项,然后在even distribution count里填上数值的话,粒子就只会在这个环的n等分点上生成(n取决于数值大小)。此项还有一个隐藏属性,就是让粒子在环上按顺(逆)时针的方向逐步生成,而不再是在环上随机取点了。

2、Position along path sequential/random
这一项其实没什么好说的,只要规定两个控制点,粒子就会在它们之间的路径上生成。参数里有关于bulge的两项,其实作用就是让两点之间的路径“突”起来。有兴趣的话可以参见电棍抽攻击的特效,里面用到了这个参数。

3、Position modify offset random
给粒子的初始位置增加一个offset. Offset可能有的人会理解为“补偿”,其实意思就是给个额外的修改而已(in addition to what you’ve already done)。在我们对初始位置进行各种设置之后,position modify offset random可以进行一些额外的修改,比如整体“拔高”粒子的位置。


4、Position modify placed on ground
和上面那个差不多,只不过这个强制把粒子放在地面上。可以设置离地高度。


5、Position modify warp random
可能是Position系列里唯一需要讲解的东西了,关于它的效果,可以参见风杖特效,找到这一项然后去掉看看有什么不同,语言实在是有点难以表达。这个效果的本意是按比例缩放粒子到发射区中心的距离,比如我们有一条Position with in sphere random,让粒子在r=100的球形区域里随即生成,那么warp就可以把这个球形区域改成椭圆。
但是我所见到的用法,都是在用这个方法的“副作用”。Warp在改变初始位置的同时,也会改变初始速度。这就是为什么在吹风特效里,后期的特效都堆在下部而不是像前期一样“向上飞”。如果你对warp这个方法有兴趣的话,请研究吹风特效。


6、Position at model random
这个我觉得也不需要讲解,只是在模型上随机找生成位置而已。这一条需要把粒子绑定到单位身上才能生效,不然编辑器也不知道你想要的是哪个模型。所以这条的效果基本上是没法预览的。

对于第一章静态系统来说,以上这些initializer差不多够我们玩一阵子的了。其实还有很多initializer没有提到,大部分是因为它们太冷门了,剩下一些initializer的原理和上面讲过的非常相似,就不再提了。

1.5.1 Operator终于要讲到operator了。可以说这个部分是编辑器的精髓,是静态系统向动态系统进化的关键。我直接放出几个最常用的Operator,它们都很好理解:
1、Radius Scale
可能是整个系统里最常见的Operator之一了吧。原理很简单,放大/缩小粒子的半径,可以自由调节速率和时间。


2、Alpha fade in/out
淡入淡出,无需多言。


3、Rotation spin roll/yaw
让粒子转起来,很简单。


4、Color Fade
颜色渐变特效。


5、Movement lock to control point
非常常用的Operator, 效果是让粒子随着控制点移动,试一下就能明白。


6、Oscillate vector/scalar
这个Operator        可以使粒子的某项标量/向量进行周期性改变。可以达到“反复横跳”或者颜色变换等效果。下图用了两个Oscillator.
jump.gif


7、Cull when crossing plane/sphere
这个Operator其实挺偏门的,拿出来讲只是以为我在后面的某个粒子里打算用到它。原理其实很简单,把plane/sphere以外的粒子都删掉,只保留内部的部分。


8、Movement max velocity
这个Operator有个好基友,ForceGenerator里的Pull toward control point. 只要给Pull toward control point填上一个巨大的参数,粒子出生之时就会具有超高的加速度,但是受限于Movement max velocity的限制,它最高也只能达到我们设定的速度,然后朝着控制点慢慢飞过去。这个用法用来做投射物再适合不过了,尤其是那种需要拐弯的。官方设计师很喜欢用这个套路…所以学起来吧。


9、Movement rotate particle around axis
一种不太一样的旋转,名字已经足够直白了。


10、Set control points(系列)
终于讲到这个系列了。这个Operator说菜也菜,除了设定控制点以外什么也干不了,但是说强也强,因为控制点可以说是粒子系统里最“高级”的控制方式了。教程写到这里我一直都没有介绍控制点的概念,是因为我觉得目前为止我们还完全不需要这个东西。确实,几乎所有的官方特效都依赖于控制点的操作,但就像我在最前面讲的,快速学会怎么用控制点其实没什么用,这样做出来的特效也很粗糙。只有理解对应的Initializer和Operator的方式,才能正确地操作特效。所以现在只要知道,这个Operator是操作控制点的,就足够了。


1.6 一些新的概念
说出来你可能不信,掌握以上的Initializer和Operator之后,我们能做的事情已经非常非常多了。但是打开一个官方特效,我们可能还是看不懂很多东西。其实我们只是不知道一些概念而已,这些概念非常简单,但对于我们理解整个特效系统是至关重要的。

1.6.1        子特效
概念本身没什么好说的,重点在于理解子特效与父特效的关系。
1)子特效默认继承父特效的控制点位置(或值)。
2)子特效可以拥有自己的控制点位置(或值)。
3)在父特效中,有一系列方法可以操作子特效。

1.6.2        Base Properties
该项位于左侧(默认左侧)Functions面板的最上方,包含了关于“整个粒子特效”的很多信息。包括radius, lifetime, color, normal,max particles等。这些参数都可以被Initializer所覆盖,而在没有被覆盖的时候,它们也会生效,所以不要忘了这里面一些参数的存在。

1.6.3         Renderer
我们前面提到过,renderer决定了粒子(图片)的“行为”,而它本身也包含了很多信息。这篇教程里将要讨论的renderer种类有:
         Render blobs
         Render deferred light
         Render models
         Render projected
         Render rope
         Render screen shake
         Render sprite trail
         Render sprite

其中,有些属性是大部分粒子类型都具有的,比较重要的有:
1、orientation type 这个参数决定了图片是“朝着”哪里的。默认的Screen Align=图片始终正对着观察者,World-Z align表示图片始终面对world的Z轴方向,等等。
2、Color and alpha adjustment -> overbright factor 这个参数表示“亮度”。在调色方面非常有用。
3、Animation rate 如果我们的粒子texture是动图的话,这一项可以设置动画速率。
4、没了。
没错,上面三个参数就已经能满足我们的基本需要了。

还有一些参数是某些例子类型特有的,值得关注的大约有这样几个:
1、Render sprite trails
          a)amount to scale length by
          b)amount to taper the width of the trail end by
          c)How long before a trail grows to its full length
它们的名字已经说明了一切。看不懂的请查字典。


2、Render ropes
          a)Texture coordinates下的一系列texture scale/offset
          这里有必要解释一下rope的行为。在rope里,每个粒子都是上一张图片的“尾”,和下一张图片的“头”(所以我们可以发现所有rope材质的贴图,它们的“头”和“尾”都是可以完美贴合的)。因此,如果两个粒子之间的距离太近,图片就会被“挤扁”(图片的“宽度”由radius决定,长度由粒子之间的距离决定) ,这样一来整个rope就会变成一坨。为了解决这个问题,我们可以调整粒子之间的距离,也可以调整texture scale, 让“一坨”图片被拉长。
          b) Texture coordinates 下的 texture V scroll rate
          这一项可以让贴图沿着整条rope滚动,可以实现很多效果。

1.6.4       粒子系统的一生(周期)
请看两张图。
single_particle_lifespan.jpg system_lifespan.jpg
图片里各个阶段的“长度”不代表他们有多长!
事实上initializer在一瞬间就完成了它的所有操作,第一张图里的青色部分只是表示“有这么一个阶段”,不表示这个阶段要花掉一定的时间
同理,第二张图里的Operator长度各不相同,但是这并不代表上面的比下面的更长! 接下来我会讲解图里出现的所有概念:
Initializer:前文已经说过了。
Operator:也已经说过了。
Lifespan:从粒子被创建的那一刻到粒子被销毁的那一刻。不一定是个定值!
Endcap:一个粒子系统的“收尾阶段”。Endcap的概念有些微妙,请尽可能地去理解这个概念。你可能会想知道,为什么粒子编辑器要设置这样一个阶段来“收尾”,答案是,“编辑器不知道什么时候该终结这个粒子”。请考虑下面这个例子:我们发射一支箭,这支箭在射到人的时候会爆炸。这是一个很简单的逻辑,但是编辑器怎么知道什么时候箭会射到人呢?它完全不可能知道(如果我们稍微修改需求,让这支箭射出三秒后爆炸,那么我们就完全不需要endcap了,请理解这两个情景之间的区别)。
为了解决这个问题,我们才引入了Endcap的概念。当这个箭射到人的一瞬间(比如KV里OnProjectileHitUnit事件被触发了),我们就启用Endcap阶段,人为地告诉粒子系统“你该炸了”,然后它就会爆炸(...)。
然而Endcap远比“射到人就爆炸”这种功能强大得多。利用它我们可以做到更多更复杂的事情。在动态系统中我们会更多地提到它。现在只要知道它的存在,并且知道它是一个需要人为触发(而不是自我触发)的阶段。
如果你能理解上面那段话,你就能理解Endcap是一个系统的一个阶段,而不是一颗粒子的阶段。这也就是为什么,所有粒子的endcap都只能在同一时刻被一起触发。

1.6.5 控制点能做什么
对控制点的终极概括,我认为是“一个三维向量”。所以它不仅能表示位置(xyz),也能表示一个欧拉角(roll,yaw,pitch),还能表示一个颜色(rgb)。同时,一个三维向量也是“三个标量”,也就是说它能同时储存标量的信息,比如半径,比如时间,等等。所以控制点几乎可以掌控粒子系统里的一切量,这也是为什么它有着如此重要的地位。



回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2017-11-24 09:08:09 | 显示全部楼层
本帖最后由 Greg 于 2017-11-27 13:26 编辑

这两天感恩节放假了…稍微高产一些。此楼的图片还没传,马上会补上。我先把楼占了。

1.7 第一次实战
接下来我们要真正进行一次实战了。我们的目标是复制TK刷机器人时的施法特效,如下图:
【图挂了…不知道为什么暂时传不上来,不过问题不大】
粒子文件的名称是tinker_rollermaw_motm.vpcf
但是我们不会做这个特效的每个子特效,我们只做其中最有意思的那一个,也就是地上的网格部分。如下:
grid.gif

在开始加入各种InitializerOperator之前,我们先分析一下这个网格是怎样被画出来的:
Step1:我们先创建一个“模板”粒子系统,该系统内的每个粒子均匀分布在一条直线上,如下图:
dummy_generate.gif
Step2: 每当模板粒子中新生成一个粒子,我们就在这个粒子的位置上画一条垂直的“线”。

听起来似乎只是简单的两步走,但是我们需要把我们脑子里简单的想法转化成粒子系统的语言。那么我们先来“翻译”Step1:
“让粒子在一条直线上逐渐生成” 这句话里,有两个关键词,直线和逐渐,分别对应两个方法:
1、直线 =  Position along path sequential
2、逐渐 =  Emit Continously
还算简单,对吧?我们再来翻译第二句:
“每当模板粒子中新生成一个粒子,我们就在这个粒子的位置上画一条垂直的‘线’”
关键词和它的对应如下(我会解释每个方法的作用):
“每当..生成...就” = Enable children from parent particle count
“在这个粒子的位置上” = Set per child control point from particle positions
“垂直” = 我们要操作控制点来确保线与线垂直。

请尽可能地暂时忽略掉所有的细节(例如如何控制线的长度,线从哪里开始又到哪里结束,这些我后面都会分析),我们现在的任务是去理解这个粒子系统的基本“机理”。用人话来说,粒子编辑器是这样画出这个网格的:
每隔很短的一段时间,模板粒子就在一条线上生成一个粒子。在这个粒子被生成的一刹那,一个子特效(也就是一条粒子带)被启用。于此同时,子特效的控制点被父特效所设置,于是它出现在了它应该出现的地方,并被设置为垂直于模板粒子所在的那条线。系统会如此循环,直到模板粒子走到线的尽头。

我们先来实现这个模板粒子。可以看到,仅仅三个function就能产生我们想要的效果。通过设定Position along path sequential的参数,我们规定了这条线从控制点#2开始,到控制点#3结束,并且这条线上能一共能画32个粒子。
dummy.png dummy_2.png

既然我们已经发现,每一条垂直的粒子带都是一个子特效,我们自然要先做好这个子特效。同样遵顼“最简化”的原则,下图中的几个简单的方法也足够满足我们的要求了。同样通过设定Position along path sequential,我们规定子特效的粒子带从#5开始,到#6结束,一共也是32个粒子。请注意,在子特效里我们用了两个“set single control point position”来手动设置控制点#5#6的位置,分别是(0,900,0)(0,-900,0),而且control point to offset position from这一个参数表示,#5#6的位置,是相对于#4而言的! 这非常重要!
child_line.png child_single_control.png

接下来只要把子特效(粒子带)添加进父特效(模板粒子)即可。你可能会想,按照我们这个设计思路,岂不是需要很多很多条粒子带?不要怀疑自己,V社的官方做法就是添加了32条粒子带,而且每一条都需要我们手动添加。我们也可以不要加那么多,如果你比较懒的话可以从56条开始,先看看效果如何(如果只用5、6条的话,我们当然也要相应地修改模板粒子里的粒子数量)。

那么接下来,我们要做的只有一件事:
在这个粒子被生成的一刹那,一个子特效(也就是一条粒子带)被启用。于此同时,子特效的控制点被父特效所设置,于是它出现在了它应该出现的地方,并被设置为垂直于模板粒子所在的那条线。
(这件事还蛮长的…)

通过我们前面的“翻译”,我们已经知道,其实这么长的一件事只需要用两个function就可以解决。Enable children from parent particle count Set per child control point from particle positions
第一个function的参数如下。可以看到我们总共要“开启”32个子特效:
enable.png
第二个function的参数如下。如果你前面留意了“#5#6的位置,是相对于#4而言的”这一句话,那你现在应该恍然大悟!通过把控制点#4设置到模板粒子的位置上,我们实际上设置了子特效的控制点#5#6,也就是粒子带的位置。为什么不直接设置#5#6呢?因为编辑器里没有任何一条function能完成“把控制点#5设置到该粒子位置向上900个单位的位置上”这样的操作。只是单纯的没有而已,所以我们才引入#4来完成这个操作。
set_per_child.png

如果上述操作都正确完成的话,我们现在应该已经能看到一个非常原始的网格了。然而有一点非常和我们想象的不一样——它是方形而非圆形的。你可能会想到,我们需要改变每个粒子带的长度,才能画出圆形的网格,但是哪一条function才能动态地修改#5#6的位置呢?更复杂的是,对于圆形来说,粒子带的长度变化甚至不是线性的……
事实上,每当我们陷入这样复杂的思考时,就说明我们的思路错了。我可以确定地告诉你,粒子系统是一个特别直白的系统。而且99%的时候它和人脑一样,是线性的。如果你发现你需要用一些很复杂的手段才能实现某些特效,那说明你用错了!
那么正确的画圆方法是什么呢?是我们在讲Operator时提过的Cull when crossing sphere。如果你之前没有记起来这个方法的话,那你现在应该再恍然大悟一次。这个function可以把球体之外的粒子都“切掉”,那么方形的网格自然也只剩下圆的部分了。请注意这个function的工作方式,球心只能被设置为某个控制点(而非粒子)+ offset,而半径可以任意设置。此外,这个Operator只会对当前级别的特效起作用,也就是说我们需要把它加入粒子带(在本例里它是子特效)的特效中,而不是模板特效(在本例里它是父特效)。
现在你应该能看到一个近乎完美的圆了。接下来我们要对它进行美化。


回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-1-20 08:39:21 | 显示全部楼层
1.7.2 美化
上一节真的非常长,不过长有长的好处,我们现在已经对这个TK的这个特效有了非常深刻的理解。能够看见一个逐步生成的网格确实很激动人心,我可以肯定地说,这已经是所有粒子中相当复杂的系统了。但是它离一个真正“可用”的特效还有很远的距离,可能你已经发现了,这个例子系统有着这样那样的缺陷,比如不会淡入淡出,不会自我消亡,也没有颜色。实现它们并不复杂,但是要达到这些艺术元素的完美平衡,其实也不是一件易事。
废话不多说,我们开始进行美化。以下方法均是加在子特效,也就是“粒子带”里的。
0、一个好的Texture很重要!如果你一开始使用的是默认的Sprite的话,你可以试试官方使用的Sprite: “materials/particle/particle_flares/aircraft_white.vtex”
1、首先添加Lifetime和Decay, 让粒子能够正确地消亡。让Lifetime的Max比Min略大一些,看看会有什么效果发生。
2、添加Radius random, 设置粒子半径。
2、添加Radius Scale, 让粒子逐渐变小,之后才平滑地消失。
3、添加Color random, 让每个粒子的颜色有些微弱的不同。
4、添加Color fade, 让粒子在逐渐消失时颜色逐渐变深。
5、添加position modify offset random, 让粒子稍稍地比地面高一些。
最后给父特效,也就是模板特效加上Stop effect after duration和Lifespan Decay, 让父特效也能正确地消亡。
我们的第一个“大工程”到此就结束了。如果你能理解上述教程中的绝大部分,那恭喜你,你已经掌握了粒子系统的基本工作方式。
回复 支持 反对

使用道具 举报

0

主题

2

帖子

40

积分

Lv:1 隐谧贤者

UID
12621
金币
94
精华
0
节操
0
发表于 2018-1-24 11:14:38 | 显示全部楼层
一直关注这个帖子,放假回来看到更新了,必须要顶一下,辛苦楼主
回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-1-28 13:59:20 | 显示全部楼层
本帖最后由 Greg 于 2018-1-29 12:37 编辑

(图还没做…过几天会补的
第二章:动态系统

2.1 前言
总算是说到动态系统了,在教程开始之前有必要详细讲一下什么是动态系统,以及为什么我们要把整个粒子系统分成动态 / 静态。
简单来讲,“动态”指的是“具有随机应变的能力”。随机应变也就是说,一个粒子系统的各项属性,在任何时候都可以根据我们的需求做出相应的改变。比如说,我们希望一个粒子一直存在于游戏内,直到某个事件被触发,例如“A玩家释放了X技能”。那么这个粒子的生命周期长度就具有了随机应变的能力,它的时长是动态的,而不是静态的,一成不变的。
对于一个静态系统来说,它的一切属性在一开始就被决定了。例如,100个粒子将在1秒内被均匀地发射,然后获得一个向上的,定值为100的速度;再花0.35秒完成淡入,最终在三秒之后消失。这个过程内的所有量都是已知的,是被写在粒子文件内的,而且是无法改变的。也就是说,这个系统的自由度,很低。
那么对动态系统来说,它的自由度就很高。这个系统里的非常多的量,其实是“不可知”的,就像薛定谔的猫一样,它的状态不到最后是无法被确定的。所以很显然,静态系统里的那种填表式的创作方式,在动态系统里是行不通的,因为我们根本不知道这些值应该是什么。

2.2 建立量与量的联系
动态系统说白了是一种对量的控制方式,而这种控制方式基本上有两种:
1)用一个量控制另一个量,即“建立量与量的联系”,也就是这一章的内容。
2)用事件/控制点来影响量。这是2.3的内容。

量与量的联系,体现在粒子系统里只有一种方式,即众多的Operators和Initializers,或者更具体一些,是它们中一系列的“Remap”方法。点开Operators/Initializers我们就会发现,其中有着一大串的以“remap”开头的方法。
remap_list.png

这个词翻译成中文,有的翻成映射,有的翻成重绘,个人觉得映射更好一些,因为它体现了两个量之间的关系。不要被这些名目众多的remap方法给吓到,它们能做的其实只有一件事:根据一个量来确定另一个量。

那么,有哪些量是我们经常会用到的呢?看完下面这个列表你就会明白,为什么remap方法如此的强大:
remap_property1.png remap_property2.png
如图里所示,我们用了“remap scalar”这个最简单的remap方法。可以发现,图里出现了两个“域”,input field和output field,这两项里面可以选的东西是完全相同的。域只是一种玄乎的说法罢了,其实它只是表示“量的种类”,比如大小,透明度,生命周期这些和粒子有关的量而已。所以这两项就决定了,我们要用哪一个量去决定哪一个量——随便组合一下吧,我们可以实现非常多的功能:
根据粒子的出生时刻决定例子大小;
根据粒子的出生时刻决定粒子透明度;
根据粒子的大小决定透明度;
根据粒子的透明度决定粒子周期长短;
........
假设我们要做一个喷泉的特效,并且还要设计出喷泉被逐渐关闭的特效。“逐渐关闭”是什么意思?很简单,水约喷越少。这个时候静态系统就束手无策了,但是运用上面举例的第一个和第二个功能,根据粒子的出生时刻决定例子大小 和 根据粒子的出生时刻决定粒子透明度,我们可以轻而易举地实现这个功能。越晚出生的粒子,它的半径和透明度就越小,而这恰恰是“约喷越少”所需要的。
请看下面两张图,对比一下他们的区别。第一张是加入了“逐渐关闭”效果的,第二张是没加入的。
spring_good.gif spring_bad.gif
有了这样一个思路之后,我们就可以着手去实现更具体的部分了。假设我们的喷泉会持续喷射3秒钟,这段时间内生成的所有例子半径都为10,透明度都为255。从第四秒开始逐渐减少喷射量,到第五秒的时候完全停止,这样整个周期的长度为四秒钟(别被搞晕了,第五秒之前只有四秒钟)。

这个时候我们需要去设置具体的映射关系了。上面两张图里还有另外四个参数,input minimum, input maximum, output minimum, 和ouput maximum. 这四个参数就是用来设置“映射关系”的,这四个量分别为输入和输出规定了一个范围,只有在输入范围内的输入才会被接受,而对应的输出也会严格处于输出范围内。

在喷泉的例子里,我们的输入范围是3-4秒,在3.0以前的粒子都会正常发射,不受这个operator的控制。我们的输出范围则是10 - 0。这里有一个非常奇怪的地方,即我们需要把10填在“minimum”而把0填在maximum里,尽管稍有常识的人都能看出10>0这件事情。原因是,最大和最小在这里只是一个名字而已,和实际大小并无关系。它的意义仅限于“对应”,即output minimum永远对应input minimum, output maximum 永远对应 output input maximum。所以在input从3走到4的过程中,output会从10走到0。如果我们按照严格的数学关系反过来填,那么粒子的半径会从0逐渐变成10,即慢慢增大而非慢慢减小。并且在3.0s之前生成的所有粒子的半径也都会是0。所以说,我们实际上在3 - 4与10 - 0 之间建立了一种一一对应的关系,此乃“映射”之真谛。
回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-2-20 13:10:32 | 显示全部楼层
本帖最后由 Greg 于 2018-7-5 23:50 编辑

进阶教程:怎样看懂和拆解一个粒子特效

不知道第一张第二章是否能为各位提供一个对粒子系统的基本概念。可能这两章里并没有提到很多“具体”的内容,例如这个Operator或那个Initializer的具体用法。相反我阐述了很多很多的“哲学”理念,静态为何是静止的,动态又动在哪里。这些可能并不能给刚开始学习粒子系统的人直接的帮助,但是实际上了解这些基本思想,能帮助我们看懂很多东西,并且举一反三。在了解Remap的工作原理之前,随便打开一个特效,看到里面名目众多的Remap函数,任何人都会感到无从下手。但是一旦明白了“任何Remap的实质都是映射关系”这个道理,再看这些陌生的函数就不会感觉吃力了。只需要找到两个(或以上)映射量外加一个映射关系,这个函数的功能就一目了然了。

那么那些具体的用法从哪里学呢?我的意见是,从实践中来。在教程中我已经尽可能多地涵盖了我认为常用的函数,但这些也只是冰山一角,何况真正掌握它们的用法,理解他们能“做什么”,还是要靠真正的实践。因此我决定在动态系统后讲解这一章的内容,即如何看懂一个复杂的特效,如何为我所用。

我们选取Dota中最炫酷的特效之一,SF的大招(至宝特效而非普通技能。实际上它们的原理是一模一样的,只是至宝好看一点而已),作为这一章的例子。

首先,第一个问题不是怎么拆这个特效,而是怎么找到这个特效。V社对特效的明明并不是很严格,所以搜到我们想要的特效未必有那么的轻而易举。就影魔特效而言,输入“SF”确实能找到至宝特效,但是出来的这一堆结果里却没有原版的技能特效。这是因为原版特效是以“Nevermore”来命名的。新玩家可能并不知道这个是Dota1里影魔的名字,所以说,这就是V社一个坑爹的地方了...

(如果你往搜索框里输入“lanaya”(TA的名字)的话,你会发现出来一堆TA的技能特效,确实是以templar_assassin* 命名的,但是它们所在的文件夹名却还是lanaya...没记错的templar assassin还是后来改的,以前必须要用lanaya才能搜到TA的技能…
最奇葩的可能是宙斯的技能了。输入Zues的话,你只能看到一共11个特效,为什么呢?因为人家的名字其实叫Zuus...相信我这不是宙斯的别名,估计就是打错了)

总而言之,时刻记住你想要的特效不一定就是你知道的那个名字。多尝试一下总会找到的。

言归正传。在搜索框里输入“sf arcana requiem”,可以看到所有SF的至宝大招特效。
一般来说,我们首先要关注的是顶级特效,也就是左下角带有P(prime)的那些。这是所有子特效的综合,是最终的效果,也是我们最后需要用代码去调用的特效。如果一个特效的左下角是P|C,则表示这个顶级特效不含有子特效。这种情况下,这个特效有可能是被废弃的(甚至是官方的特效也有可能),出于某种原因被创作出来但是没有被使用。我们只要把它忽略就可以了。

我们会发现这些特效里一共有两个较为复杂的特效。
1.P|3 sf_fire_arcana_requiemofsouls.vpcf
2.P|5 sf_fire_arcana_requiemofsouls_line.vpcf
分别点开看一下吧。

乍一看,这两个特效都很令人摸不着头脑。一个是一闪而过的红光,另一个是一坨火焰,一点也不像SF的炫酷大招。这时我们面对的有两个问题:
1.部分特效没有得到展示(红光一闪而过显然是一个太过简单的特效了
2.所见特效和最终效果不符。
一般来说,我们检视一个特效,如果能不去窥探它的底层实现而直接使用,这是最好的。如果你懂编程里接口这个概念的话,使用粒子特效的最佳方式即是按照接口来使用。可惜例子系统没有自带的参考文档,我们只能自己去研究了。

我推荐按照以下的几个点去拆解一个特效:
1、先看控制点。绝大多数特效无法展示的原因是控制点没有被正确设置。如很多的AOE特效是根据cp(控制点,下同)的值来确定特效范围的。在我们刚点进一个特效的时候,所有的CP(除非以其它手段提前设置)都仍处于默认状态,所以会导致半径为0这样的情况出现。一个复杂的特效里可能会有十几个CP, 但是所幸并不是每一个都需要被设置的。基本上我们会用到的特效都只有两三个CP需要手动设置,而且更贴心的是,我们能从编辑器右侧的CP列表直接“看出”哪些CP是长这样的。如下图:
CP_DATA.png

一般来说,带有蓝条的CP是需要手动设置的,而且需要设置的那个分量里还会有个“1”。这表示这个CP是被当作“值”而非三维矢量来看待的。我前面已经提到过对CP的理解,如果忘了可以再去看看。

2、再看粒子的renderer
在正确设置了CP的情况下若仍不能看到正确的特效,那很有可能是Renderer的问题,因为并非所有的Renderer都能在编辑器里被预览,必须要放在游戏中才能看见。遇见这种情况的时候,我们需要手动去找Renderer, 看看问题是不是出在这里。

3、接着看粒子的生命周期
生命周期指的是lifetime / endcap 这些东西。我们无法看到特效也可能是因为特效的主体其实存在于Endcap。点击预览窗口上方那个星号按钮[Stop sim with endcap]即可看到endcap。

4、各种奇怪的问题
如果上面三步还不能让我们好好使用这个特效的话,我们只能手动去拆解它了。这其中包括很多奇奇怪怪的问题,包括粒子编辑器本身的BUG,后面会细讲。

OK 下面先看第一个特效:P|3 sf_fire_arcana_requiemofsouls.vpcf。我们还是按照上面三步来。

        第一步看CP。我们发现控制点1是一个需要设置的CP,很有可能是半径。那么随便来设置个数,500好了。完了我们会发现,其实什么也没发生。
        (剧透:实际上CP1是控制粒子发射量的,而且毫 无 卵 用

        第二步看渲染方式(renderer)。双击打开第一个子特效,我们发现,这是一个Render Projected:
         projected.png
        再点开第三个子特效,一个Render screenshake。
OK,问题解决。Projected和Screenshake都不是能在编辑器里预览的东西,我们可以洗洗睡了。(接下若干楼的教程



回复 支持 反对

使用道具 举报

0

主题

2

帖子

40

积分

Lv:1 隐谧贤者

UID
12621
金币
94
精华
0
节操
0
发表于 2018-3-6 10:01:14 | 显示全部楼层
请问楼主这个帖子还有后续吗

点评

会的 只是要拖比较久…  发表于 2018-3-29 10:52
回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-3-28 16:11:58 | 显示全部楼层
本帖最后由 Greg 于 2018-7-5 23:54 编辑

【抱歉这段时间鸽了很久 学期末实在是太忙了】
【这段时间我会努力更新的 前面没传的图也会尽快补上】
【谢谢大家 以下是新内容】

接下来我们开始分析上述两个“比较复杂的特效”中的后者,即P|5 sf_fire_arcana_requiemofsouls_line.vpcf
实际上这个才是特效的主体

点开这个特效之后我们应该感到一种冲动,忍不住要去看这个粒子的控制点是什么。确实,控制点携带的信息实在是太关键了,比这个特效本身长什么样更加关键。该特效的所有控制点如下图所示:
sf_ac_cplist.png
其实这个特效并不复杂,一共也只有四个CP而已。我们首先发现的是CP2,因为这是一个“量”控制点(带“蓝条”的控制点)。那么我们先尝试往里面填几个值。
sf_ac_cp2=0.2.gif sf_ac_cp2=1.gif sf_ac_cp2=2.gif 以上为CP2 = 0.2 / 1 / 2时的特效
我们会发现,CP2显然是和持续时间有关的,但是它表现出了一种非常奇怪的方式——如果CP2小于1,粒子的持续时间明显减小了,但是如果CP2大于1,甚至调到999,粒子的持续时间都几乎没怎么变。

为什么会这样?很显然,这个粒子里有某种特殊的设置,或者说特殊的机制,使得这个CP变得如此奇怪。但是这种机制具体是什么,我们暂时不知道。不过我们马上就会弄清楚的。

这个特效里还有剩下的三个CP,但是我们并不会挨个分析他们。实际上,对于绝大多数的粒子特效 ,我们都只需要操作一两个CP就足够了(如果你研究过足够多的特效你大概也会同意这一点)。所以我推荐的策略是,只去关心那些有明显作用的CP就好。比如说我们上面已经研究过的CP2,和这个特效里的CP1。如果你往任意一个方向拖动CP1一段距离的话,你会发现这个特效朝着那里飞过去了。很显然,CP1是控制粒子发射方向的控制点。实际上,绝大多数的粒子都会选择CP1作为控制位置和方向的控制点,所以看到CP1的时候我们就应该猜到,这很可能和粒子的位置/方向有关。

CP3和CP0在这个特效里算不上重要。CP3可以说是毫无作用,CP0的话只是改变粒子的初始发射而已。和CP1通常掌管发射方向一样,CP0通常是掌管粒子的(初始)位置的。这些算是不成文的规矩,有个印象就好。

接下来我们要解决刚刚没有被解决的问题了——为什么CP2会表现出这样的行为?
如果我们把CP2还原至初始值1, 只拉开CP1的距离,特效将会如下:
sf_ac_block.gif
可以看到,粒子已经基本成型了,只是在它飞到CP1的时候会被“挡住”,有一些些的不完美。在游戏里这个特效显然不会被挡住,说明我们的特效设置有一点点的问题。
你可能会想,是不是CP1设置的太近了以至于这个特效没有足够的飞行距离,于是被挡住。答案是不,如果我们把CP1拉的很远很远,只会加速这个粒子的飞行速度,飞到尽头时仍然会被挡住。
神奇的是,如果我们把CP2改为2的话,这个粒子突然就正常了,如下图:
sf_ac_no_block.gif
那么,CP2到底改变了什么?
我们把光标放到CP2上,发现并没有显示任何的信息,这表示这个CP只在当前特效(父特效)中被使用。如果这个CP是从子特效中拓展过来的话(意思是子特效中运用了这个CP),会像下图这样显示:
cursor_cp3.png
那么我们只要在当前特效里找,哪个Operator或者Initializer使用到了CP2即可。可以发现,只有“Stop effect after duration”这个operator用到了CP2。因此我们可以隐藏所有的子特效,只关注父特效的机制就可以了。
取消掉所有特效之后,屏幕上还剩下什么?你没有看错,确实是什么都没有。我们发现,父特效甚至连Renderer都没有。如果你还记得我们前面做过的那个TK特效的话,这时候你应该隐隐约约地觉得,这很可能是一个“模板粒子”——尽管它没有被渲染,但是它的位置和运动信息仍然会被生成(当然你也可以添加一个Renderer然后隐藏这个Renderer,这其实是一样的效果)。
为了让这个没有被渲染的例子“现形”,我们人为地加入一个Render sprite:
sf_ac_dummy.gif
根据上面这张图我们几乎可以断定这是一个模板粒子了。所有子特效的位置都绑定在了这个白色粒子上,白色粒子移动到哪里,子特效就跟随到哪里。我们之前已经提到过这种“模板特效” --> 控制点 --> 子特效”的设计模式了,这确实是一个非常常见和好用的套路。它的具体实现依赖于两个核心Operator:
1) Set child control point from particle         positions (位于模板特效中
2) Movement lock to control point (位于子特效中
其中第一个Operator建立了(模板)粒子位置和控制点之间的联系,粒子飞到哪里,控制点就被设置到哪里。当然我们可以自由选择要设置的CP。
第二个operator建立了子特效和控制点,控制点被设置到哪里,子特效就跟随到哪里。所以很好理解为什么第一个Operator是放在模板特效内而第二个是放在子特效内的。
现在我们已经理解了这个特效最核心的工作方式,要理解CP2的工作方式也就不难了。我们之前说过,CP2是在stop effect after duration里被引用的,但是它控制粒子持续时间的方式,比这个Operator的字面意思要复杂一些。你可能会觉得,我们只要把这个Operator设置成这个样子,然后只要修改CP2的Y分量就可以控制该例子的持续时间了。
stop_conf.png
实际上,“stop”在这里的意思仅仅表示“停止发射”然后进入(也可以不进入,取决于参数)endcap,它并不会负责删除掉这个粒子。“删除”是由一系列名字里带“decay”的operator完成的。除非你勾选了“destroy all particles immediately”这一项。但是这通常是和我们想要效果背道而驰的,因为“immediately”往往意味着粒子会被很突兀地删除,而我们当然希望我们的粒子特效越平滑越好(至少在绝大多数情况下是这样)。更何况,如果你勾选了这一项,所有的子特效也会被一并删除。这样看来,它的威力实在是有些太大了。我们需要一个更温和的方式来控制粒子的消亡。
官方特效是怎么做的呢?它用了一个“lifespan endcap timed decay”。顾名思义,这个Operator的意思是“在粒子进入endcap一段时间后删除这个粒子(有别于destroy all particles immediately, 这个operator只影响它所在的当前特效而非所有子特效)”。
这个Operator里有个参数叫Decay time,它规定了上面所说的“一段时间有多长”。
timed_decay.png
可以看到官方特效里这一项被设置成了0,也就是说,当这个粒子进入endcap的0秒后(也就是立即)删除这个粒子。
我们现在完整地梳理一遍这个特效对粒子持续时间的控制:
1.首先,一个例子被发射。
2.一段时间后(CP2的Y分量所设置的时间),stop particle after duration 被触发。所有粒子进入endcap。
3.lifespan endcap timed decay接管了特效,在进入endcap的0秒后删除了所有粒子。
所以实际上,cp2的Y分量就是粒子能存活的秒数。这也就是为什么,当CP2的Y = 1的时候,整个特效会被“挡住”。粒子发射一秒之后,模板例子被删除,“Set child control point from particle positions”无法找到模板例子的位置,所以所有子特效的CP0也就停在了它最后存活过的位置上,不再前进。而此时子特效的动画还未播放完毕,所以它会停在原地直到自己也消亡为止。而当CP2足够大的时候,模板特效会在子特效全部播放完毕之后才被删除,也就不会产生“被挡住”的效果。【未完待续】

回复 支持 反对

使用道具 举报

0

主题

1

帖子

1

积分

Lv:1 隐谧贤者

UID
12950
金币
3
精华
0
节操
0
发表于 2018-5-18 18:00:53 | 显示全部楼层
666
回复

使用道具 举报

0

主题

6

帖子

260

积分

Lv:2 长袍法师

UID
9304
金币
316
精华
0
节操
0
发表于 2018-5-29 05:24:54 | 显示全部楼层
请问大佬 , 特效里面根据英雄模型改变特效里面的模型是怎么弄的么?像蓝猫那个放电,敌法的跳,都会根据当时的模型和动作,改变特效的模型动作,这是个多年未解之迷,求特效大佬指导,还有沉默的法球,也会根据英雄手拿的武器不同而改变,在OMG里就是
回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-6-21 14:39:25 | 显示全部楼层
本帖最后由 Greg 于 2018-6-21 14:41 编辑
somejerry 发表于 2018-5-29 05:24
请问大佬 , 特效里面根据英雄模型改变特效里面的模型是怎么弄的么?像蓝猫那个放电,敌法的跳,都会根据当 ...

我只研究了蓝猫的特效,其他的应该也是相通的,原理大致是这样的:
(下面提到的各种属性都在particles\units\heroes\hero_stormspirit\stormspirit_static_remnant_image.vpcf内
1. 根据英雄模型修改特效模型。这主要是由 “remap model sequence to scale"完成的,它获取了当前英雄的模型动作,然后映射到对应的output field(至于为什么要以second sequence number作为output我不是特别清楚,但是既然是一个sequence我想也八九不离十了)。这一项里有一个control point number的属性,值为1,我猜是只要把CP1绑定到英雄身上即可,而且我测试时也发现确实是这样。我用的代码如下:ParticleManager:SetParticleControlEnt(m, 1, caster, PATTACH_POINT, "attach_hitloc", caster:GetOrigin(), true );
2. 让模型播放很短的一段动画。在render models里有一项名为” manual animation frame field"的属性,其值为“ scratch float”,可见官方特效使用了sratch float这个field来控制帧的播放。另在Operaor里有一项ramp scalar linear simple, 这个Operator直接设置了scratch float的值,也就是间接地设置了帧的播放。修改里面的属性可以达到修改播放时长/速率的效果。



回复 支持 反对

使用道具 举报

1

主题

4

帖子

37

积分

Lv:1 隐谧贤者

UID
13035
金币
29
精华
0
节操
0
发表于 2018-7-4 19:41:41 | 显示全部楼层
收藏留贴学习,谢谢分享
回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-7-6 00:06:44 | 显示全部楼层
我们之前提到只要CP2足够大,就不会出现“被挡住”的情况。至于“足够大”是多大,这取决于子特效的生命周期。本着能偷懒则偷懒的原则,我们并不需要明确地知道子特效的持续时间。反正CP2只要够大就行,而且再大也不会影响粒子的效果。当然CP2很大的话模板粒子将会持续很久而得不到清除,但毕竟我们也不会没事就把它设置成几百或几千...所以在这里我们就把它直接设为2。如果这个有些随意的方法让你很不舒服的话......
那我也没有办法。

至此我们已经基本明白了这个粒子的工作方式。按理说教程在这里就应该结束了,但是实际上我还需要讲解一下如何在游戏中实际使用这个特效。事实上这往往是粒子系统的难点所在。在粒子编辑器里看到我们想要的特效只是第一步,我们还需要在游戏中正确渲染出实际的特效。我之前说,控制点是粒子系统与游戏脚本进行沟通的方式,因此学会使用代码来控制CP是非常重要的一步。

那我们现在就开始在游戏里创建这个粒子。

既然官方特效只为我们提供了SF大招中的“一条线”,我们就只能手动创造很多条线来模拟它的效果了。这个思路也很明确,在lua里创建一个for loop 然后在18个方向上创建这个特效就好了。代码如下:

鉴于这是一个粒子教程我就不对里面用到的API进行讲解了。请参考官方文档。主要就是两个API: RotatePosition() QAngle().

需要解释的是CP和游戏世界的沟通方式。脚本里我将CP0设置为坐标原点,CP1设置为(500,0), 但是很多读者并不知道为什么是这样设置。事实上我第一次设置CP1CP0的时候也犯了一个错误,我将CP0设置为了caster的坐标而将CP1设置成caster坐标右边(500,0,0)的位置。这样一来,CP1的“运动轨迹”实际上是以caster为圆心以500为半径的一个圆。
这听起来似乎也挺对的?然而在游戏里测试的时候我们会发现,如果角色没有站在世界中心的话,这个特效会变成类似这样:
sf_ac_wrong

其中的原因是我们没有充分理解CP1到底设置了什么。在Initializor里我们会发现,CP1在一个名为“Inherit velocity from control pointInitializor所使用了。顾名思义,CP1里包含的三维向量实际上会成为粒子的速度,而这一点是有别于“飞向CP1”的。“飞向cp1是很多投射物特效所使用的方式,即粒子会无条件地飞往CP1。但是在这里CP1仅仅是速度而已,假设我们的人物站在(20002000128)这个点上,那么按照我一开始所设定的CP1,我们发射的第一条粒子速度将会是(25002000128),这显然不是我们想要的速度。

为了得到正确的速度,我们应该使CP0CP1独立于位置本身。因此CP0应当被设为(0,0,0),而CP1仍然做半径为500的圆周运动,只是在这里圆心应当是(0,0,0)而非caster:GetAbsOrigin().

修正后的粒子特效如下:
sf_ac_correct
可以说是很不错了。
这次鸽的格外地久,好像有一学期了(...)。但是我会再在这个帖子上挣扎一会儿的,希望大家看得开心。
图不知为何传不上来,前面几楼的倒是可以。我后面会补的。
谢谢。


回复 支持 反对

使用道具 举报

3

主题

23

帖子

638

积分

隐修议员

UID
7045
金币
609
精华
0
节操
-30
 楼主| 发表于 2018-7-9 20:18:38 | 显示全部楼层
本帖最后由 Greg 于 2018-7-11 17:28 编辑

进阶教程Part2 - 进一步的特效拆解与理解

我们之前所涉及到的特效,绝大部分都是针对“地面”而言的。我们一直将地面当作一块画布,然后在上面创作各种各样的特效。之前SF大招的特效可以说是很典型的一个特效,特效有足够的复杂度,与代码也有足够的沟通。我们可以说,这是一类通过代码与地面进行沟通的特效。但是事实上,很多特效并不是基于地面的,而是基于模型和单位的。“基于”的含义可以很简单也可以很复杂,它可以是“粒子跟着单位移动”,也可以是“粒子随模型的动作而变化”。在这一节里我打算拆解一个与模型/单位密切相关的特效,即PA至宝的暴击特效。它涉及到了一个模型的很多方面,包括模型本身是什么,模型的朝向,模型的大小(比例)等等。正确地使用这个特效非常地简单,事实上只需要四行核心代码,但是理解这个代码的工作方式是比较复杂的。

首先介绍一个API : SetParticleControlEnt(int int_1, int int_2, handle handle_3, int int_4, string string_5, Vector Vector_6, bool bool_7).这是一个非常复杂的API,而我对其中很多的参数的功能也没有弄明白(希望有人能指点一下,感激不尽)。但是总体而言,这是一个“将控制点绑定到实体上”的API,并且可以绑定到某一个具体的attach point(比如模型的眼睛,头顶,手上等等。当然未必每个模型都有这样的attach point)。换言之,这是一个让特效与模型产生沟通的API,非常地关键。我会在后面给出这个API在代码里的具体用法,现在只要知道它的存在就可以了。

为了让各位尽快地体会“模型与特效的沟通”,我先直接贴出所有的代码,这样我们可以直接看到实际的效果了。
pacrit code
只需创建一个点目标类型的技能,添加OnSpellStart事件,事件触发RunScript, 然后调用这个函数即可。如果你不知道现在在说什么,请先阅读技能制作相关的教程。在实际游戏中,释放这个技能即可产生特效。以下两张图展示了这个特效:
[PA_SCALE_TEST] [PA_ANGLE_TEST]

我们发现这个特效有几个比较有意思的地方:
1. 如果对大模型释放的话,产生的特效也会较大(这里的“大”指的是模型比例而不是绝对的模型体积)。
2. 施法者相对于目标的位置会改变特效的朝向。
3. 特效中的模型(也就是那个影子)的朝向和目标单位的朝向一致。

很显然,模型大小,相对位置等信息对特效而言必须是“可知”的。我们自然有很多种方法可以传递这样的信息给特效。假设我们要实现上面的“1”,其中一个直观的方法是先用API获取模型比例,再传给控制点。但并非所有的东西都能像这样实现(比如“传递一个名字”这件事就没法通过简单地设置控制点完成”),因此我们接下来要分析这个特效是如何架起特效与单位之间的沟通的桥梁的。
点开PA暴击的主特效(
particles\econ\items\phantom_assassin\phantom_assassin_arcana_elder_smith\phantom_assassin_crit_arcana_swoop.vpcf)我们可以看到两个子特效:
[PA_CRIT_TWO_EFFECT]
显然这个特效分为两部分,一个是飙血特效,一个是剩下的蓝色特效。一般来说子特效们会尽量共用控制点,所以我们可以专注于其中一个特效进行分析。我们这里选择蓝色特效入手。
点进去之后一共可以看到六个子特效:
pa_children_upper & lower
这六个特效的结构还是相对简单的。前四个特效都是相似的半环形结构,它们的具体实现我就不分析了,如果弄清这四个特效大致的工作方式让你觉得很困难的话,可能这个部分的教程对你来说有些超前了。
第五第六个子特效看起来主要是两个黑色的条状物,仔细看的话我们会发现第五个特效的缩略图还有一个蓝色的光点。点进去之后我们会发现,这个子特效的结构其实是这样的:

             [Render models 渲染模型(即上文“第五个子特效”)]
               /                                          \
        [子特效1:黑色条状物       [子特效2:附着在模型上的一个粒子特效

这时我们应该明白,我们之前在特效里看到的蓝色影子,其实是由这个renderer渲染出来的。接下来我们开始研究这个蓝色影子究竟是如何被创造出来的,我们主要关注以下几个点:
1. 它是如何拥有技能目标对应的模型的(为什么对豺狼释放这个技能就会出现豺狼的模型)
2. 它是如何控制影子的漂移方向的
3. 它是如何控制影子的朝向的
分析如下:
1的实现:
1主要由Render models这个renderer里的一项名为“model override cp”的项实现。如图:
pa_model_cp_override
如果我们填入的CP被绑定到了某个单位上(利用前文提到的那个API - SetParticleControlEnt()),那么粒子系统会自动读取这个单位的模型,并“覆盖”这个renderer要渲染的模型。所以如果我们按照先前的代码,我们会发现在这里填入 0/1/2/10都能正确地渲染出模型,而其他的CP都不行。
2的实现:
特效的“移动”有不少的实现方式,但我们一般会用的也就Velocity, force, 和绑定CP三种方式。点开“Position within sphere random”这个initializer我们会发现,speed in local system min/max 这两项给了粒子(-1200, 0 ,0)的速度:
pa_1200
local system非常关键,它告诉我们这个速度的“方向”是基于这个特效的坐标轴的“方向”的。换言之,在游戏里这个特效的坐标的X轴指向哪儿,这个特效就会飞向哪儿。如果不手动设置的话,特效的坐标轴是和游戏世界的坐标轴是默认对齐的(实际上似乎并非三个轴都分别对齐,但是最多也就是旋转90度或者180度,影响不大)。因此我们只要控制的就是这个“坐标轴”。这是我们使用SetParticleControlEnt的又一个原因。我们之前说这个API是将CP绑定到模型的attach point上面,而attach point是自带坐标轴的 - 也就是说,绑定到这上面的CP会继承这个坐标轴。这样操作的好处是显而易见的,例如我们可以把一个CP绑定到attach_attack1上,从而实现“让粒子跟随一根挥舞的法杖”这样的效果。
回到PA的特效(蓝色影子那个子特效,前面提到的即“第五个子特效”)。在Position within sphere random里我们可以看到control point number 被设置为1,那么只要把CP1绑定到hit_loc上,就完成了对速度方向的设定。这样一来整个特效会朝着单位的正后方“喷射”。
然而如果对前面那个GIF稍加观察就可发现,特效并非总是向目标正后方喷射的,它的朝向实际上取决于目标和施法者的相对位置,即总是朝着“相对于施法者的后方”。这是一个粒子系统无法直接获取的信息,因此我们需要手动设置。上文的代码截图中的最后两行代码正是实现这一功能的。我们先获取了目标与施法者之间的向量,并转化为单位长度。接着使用了SetParticleControlForward()来设置CP1的“朝向”。 2的实现就此完成。
3的实现:
我们之前说使用SetParticleControlEnt的原因之一是它可以顺带设置CP的坐标轴朝向,因此我们也可能很自然地觉得,这个粒子系统里的一切“方向”都是基于这个坐标系的。但事实并非如此。粒子的“朝向”就是一个例外,更精确的说法是粒子的”rotation”并不受坐标系的控制。当我们旋转坐标系的同时,粒子并不会跟着旋转。为了实现3的效果,我们必然要“旋转”这个粒子的朝向,使其与模型的朝向保持一致。一个Initializer可以完成这一效果,即Remap control point orientation to rotation. 顾名思义,这个initializerCPorientation(也就是朝向)映射至粒子的rotation上。它的具体设置如下:
pa_orientation_to_rotation
Control point 这一项设为了10,一个绑定到模型上的CP,并未经过旋转。
Rotation field设为Yaw, 表示这个旋转是围绕Z轴的。
Offset rotation 180,表示额外添加一个180度的旋转,否则模型是反向的。
3的实现也完成了。
PACrit_code.png
回复 支持 反对

使用道具 举报

3

主题

35

帖子

428

积分

Lv:3 空明术士

UID
1759
金币
630
精华
0
节操
0
发表于 2018-11-15 23:38:53 | 显示全部楼层
再次感谢楼主,这篇帖子对我学习理解粒子系统帮助特别大!
回复 支持 反对

使用道具 举报

2

主题

6

帖子

297

积分

Lv:2 长袍法师

UID
12570
金币
258
精华
0
节操
0
发表于 2018-11-19 13:22:27 | 显示全部楼层
本帖最后由 Ajustguguit 于 2018-11-19 13:29 编辑

最近研究粒子头都大了,国外实例也没几个,自己摸索搞懂的东西少之又少
顺便等父特效控制子特效教程,一个个改子特效真的蛋疼
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

QQ|Archiver|手机版|小黑屋|AMHC!dota2rpg~ ( 闽ICP备14009209 )

GMT+8, 2018-12-19 07:17 , Processed in 0.550677 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc. Theme.Yeei

快速回复 返回顶部 返回列表