正文
大家好这里是 WildWolf,菜鸟 TA 一枚,作为公司的技术支持,完成日常任务之后喜欢研究各种类型的效果和实现方法,这次给大家带来的是很早之前自己做着玩的一个效果——激光连续反射效果——Niagara+蓝图制作。
废话不多说,先拨片~~~
实现功能为主,效果比较搓~~~ 各位大佬轻喷 ~~~
这个功能其实难度并不高,主要是蓝图的循环逻辑以及反射角的计算,Niagara 粒子只是基本的操作~~~
一
首先进入 Niagara
真的就是常规设置
User Exposed 创建两个 Vector3
,作为 Beam 的起点和终点,然后再新建一个 Float
,给 Spawn Pro
, 这个参数官方描述的比较抽象,简而言之 如果这个参数为 0 那么无论是 SpawnRate
或者是 SpawnCount
输入任何值都不会发射粒子,防止当前粒子系统已经摧毁但是粒子发射器还没有停止工作的 BUG~~~ (个人的理解不代表官方 =。= )
接着进入 System State,修改整个 Niagara System 循环周期为 0.1 秒,让 Lifetime
读取系统的 CurrentLoopDuration
然后新建一个简单的材质,作为 Beam 的渲染,也灰常简单~~
Color 部分给了一个简单的曲线
这里需要注意的就是,Curve 默认的 CurveIndex
一般是 NormalizedAge
,也就是 粒子的生命周期归一化的值 ,但是面对 Beam 粒子,就需要改成 RibbonLinkOrder
,不然曲线是无效的。
粒子的基础设置完成,当然还可以添加 JitterPosition
扰乱效果,各位根据喜好来就行~~
二
进入蓝图操作,使用 第一人称
模板就行
简单来说就是使用一个循环来释放 Niagara 粒子,释放同时 Attach
到自己进行位置绑定,然后通过 Tick
来更新每一个 Niagara 的信息。
这里用 Insert
插入数组信息是为了需要用每一个粒子的 Index
来做逻辑判断~~~
进入重点,Niagara 信息更新
首先使用第一人称的枪口绑定的 Sphere 给 Beam 的 StartLocation
,也就是第一束激光的起点
激光方向取当前摄像机的 Forward Vector
新建一个 race Counts
用来决定激光会反射多少次,用来给 For Loop With Break
的 LastIndex
,循环的 Index
则用来标记当前的激光以便后面的逻辑判断
发射出一枚激光之后设置当前激光为 CurrentBeam
,同时设置 Beam 的起点信息 Bear Start
接着进行射线检测
默认设置 5000
个单位的检测距离然后把返回值存为一个变量 Hit?
紧接判断当前射线是否撞击到了阻挡物,若有阻挡(Hit?
为真),则把当前撞击点的位置存为下一根激光的起始点 BeamStart
,同时将其设置为当前激光的终点 BeamEnd
,接着根据反射计算下一个激光的反射方向 Beam Start Direction
(同时也作为 Hit Normal
);若没有阻挡(Hit?
为假),则直接将 Trace End
设为 BeamEnd
其实这一步逻辑很容易理解,当前射线的终点为下一根反弹射线的起点,然后依次类推,直到反弹次数上限或者没有撞到阻挡物为止~~~
那么真正的难点在于如何计算出当前射线撞击到阻挡物之后的反射方向~~~
计算方法不止一种,这里使用向量计算来实现,需要一点数学平面几何的基础~~
这里我们引入一张图,BA 为入射方向,AC 为与撞击表面法线方向重合长度为 1 的向量,N 为表面法线方向,我们需要根据这两个向量求出 AD 的方向~~~
首先假设 BA 和 AD 都为单位向量,向量长度都为 1,构建出一个平行四边形 ABCD,则
AD = AC + CD
求出向量 BA 在法线 AC 上的投影 AE
|AE| = dot(BA,-AC)
则 |AC| = 2|AE|
AC = N*(2|AE|)
再把 BA 平移给 CD,即
AD = N*(2(dot(BA,-AC))) + BA
代码转化为蓝图则为
这样反射向量就算出来了~~~,那么就满足了下一条激光射线的位置信息,通过 loop
循环,就实现了激光多次反射~~~
接着完成最后一步,当前射线更新位置遇到前方无遮挡物则需要根据 Index
的编号从高到低销毁对应射线
到这一步整体逻辑完成~~~
接着写几个反射物体,常规操作~~
使用 TimeLine
做一个简单的循环完事~~~