虚幻4 在Material中如何实现 车子压倒草的功能

Posted 黄进钿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了虚幻4 在Material中如何实现 车子压倒草的功能相关的知识,希望对你有一定的参考价值。

上次发了篇介绍车子压倒草的博文

http://www.cnblogs.com/JinT-Hwang/p/8169146.html

中的2.部分。

 

不过存在一个问题,就是如果草很多,会有很多个碰撞体,虽然物理效果比较真实但是可能会导致性能问题。

这次介绍一下在草的材质中编码,实现车子压倒草的功能。

material中会用到一些数学的知识,还需要各位有一定的概念才能很好的理解。

 

关键词:unreal4、虚幻4、汽车、草、压倒、伏地、Material、材质编辑器、Shader

 

实现思路:通过求出草离车子的水平和垂直距离(如果只判断车子离草的距离,结果周围的草会成一个圆形倒地而不是一个长方形),再根据距离让草旋转不同的角度。

 

思路详解:

1.要实现的功能如下图。

 

 

2.O点是车子的中心坐标,A是草的中心坐标,只需求出ABAC的长度,然后再跟自己设定的触发距离比较,符合就草根据距离做逐渐倒地的动作。(需要两个实现,一距离判断,二倒地动作)

 

 

3.只有OA两点的坐标还不足以求出ABAC的距离,注意上图表示的是车子本地XY轴坐标系,车子不是在世界原点。

 

4.要求出BO(AC)的长度,至少要知道CosAOB,此处可利用点乘(即数量积、点积),向量OA·向量OB=|向量OA|·|向量OB|·CosAOB,求出CosAOB后,即可求出OB的向量和OB长度。

 

5.求出OB长度后,用勾股定理即可求出AB的长度,第一个实现就完成了,第二个实现以及细节的请往下看。

 

 

一、虚幻4如何通过Material编程实现车子压倒草的功能

 

A.先创建一个MaterialParameterCollection(材质参数集合),因为material下的局限,只能通过调用MaterialParameterCollection来获取外部标量和矢量。具体介绍可参考下方官方文档。

https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/ParameterCollections/index.html?lang=zh-CN

 

 

创建后双击打开,Scalar Parameters下创建的是标量(0)Vector Parameters下创建的是矢量(0,0,0,0),此处先创建一个矢量的,命名为CarPosition,用来储存车子坐标,来传入Material使用的。

 

 

打开车子的蓝图,在EventTick事件引出一条线用于实时获取车子坐标。

 

 

车子的坐标有了,车子指向草的矢量(向量)就可得到了,还需要一个车子指向前方的矢量,此处车子的蓝图的component面板中添加一个空的组件,调整到车后底部并且对准车子的中心线。

 

 

 

在前面的MaterialParameterCollection中再添加一个表示车后坐标的矢量参数。

 

 

回到车子的蓝图中,从Event中再引一条线出来用来获取车子后面点的坐标。

 

 

B.将前面的MaterialParameterCollection拖动到草的Material里,点击该Material Parameter Collection,并在Details面板中的Parameter Name下拉框选到表示车子坐标矢量的参数,再复制一个,选到表示车子背后坐标矢量的参数。

 

 

两个坐标需要先用Mask去掉第四个坐标,将Float4转换为float3。在material里的参数、操作是以颜色RGBA码来表示的。

 

 

车尾坐标指向车中心坐标的向量,用车中心的坐标减去车尾的坐标即可得到(后面简称向量DO)。此处相减前都乘了(1,1,0),这是去掉Z轴坐标的干扰,计算的时候只要算XY轴平面的距离即可,只要2D向量即可满足。当然,也可以前面mask的时候只保留RG值组成为Float2坐标。

 

 

同理,车中心坐标指向草中心坐标的向量(后面简称向量OA)。下图的Object Position是指当前这个material的中心在世界坐标中的位置。

 

 

根据点乘的公式可得, CosAOB=(向量OA·向量OB)÷(|向量OA|·|向量OB|),此处向量OB不知道,用向量DO代替CosAOB=(向量OA·向量DO)÷(|向量OA|·|向量DO|),因为向量DO的指向和向量OB的指向相同,所以求出来的CosAOB值是一样的。

 

向量的点积,用Dot接上两个向量即可求出,向量的绝对值可用Vector Length即可求出(前面是Float2的用V2,前面是Float3的用V3)。此处有两种做法,一种是用Normal将向量归一化然后再求Cos,或者直接用本身向量长度求也可以。

 

 

可以先求向量OB,再求向量OB的长度,或者直接向量OA的绝对值乘上CosAOB直接得到OB的长度。

 

 

但是此处有一点要注意,向量OA和向量DO夹角大于90°时,CosAOB的值时负值的,会导致车子的前面部分草有压倒的反应,但是后面部分草没有反应。

 

 

要求的是CosAOB,但是当角度大于90°时,cos的值实际上是cosAOB。当AOB增大时,AOB在减小(90°->0°),由上面的cos值变化图,可以看出当角度大于90°时,要求的cosAOB跟当前的cos值时相反的关系。

 

 

cosAOB大于零时,仍使用当前的cos值,cosAOB小于零时,即乘以-1即可得到向量OB

 

 

然后即可用勾股定理求出向量OB的长度,或者用向量OA=向量OB+向量BA,求出向量OB后再求向量OB的长度。到这里草在水平方向和垂直方向离车子的距离就都求出来了,分别是|向量OA||向量OB|

 

 

C.接下来需要实现草旋转的部分。如下。RotationAngle的值需为0~1.

 

 

旋转是根据UV坐标系来旋转的,x轴向右,y轴向上,z轴垂直xy轴从屏幕出来。

 

 

(1,0,0)表示沿着本地X轴旋转,但我们需要在世界中,面向相机的方向倒下去,所以加上Transform Vector将本地的坐标空间转换成世界坐标,此处除了使用View Space也可以使用Camera Space,效果等同。

 

 

还需要自定义三个参数来做判断依据,CarLongCarWidth两个参数用来判断是否在车子底下,OutSideWidth用来结合另外两个,来判断外圈草倒地动作的范围。

 

 

上面的自定义参数,carlong储存车子长,carwidth储存车子宽,outsidewidth储存草开始触发操作,离车子矩形边缘的距离。

 

 

判断草是否在触发范围内,如下图。第一个if,出口接material上的World Position Offset,当A>B时,如果有之前有别的代码连World Position Offset上,可连在此处,否则连一个0常量即可,第二个ifA>B时,相同,当A<B时,接旋转草代码。

 

 

草旋转倒地也要做判断,当草在车子底下时为倒地90°,在车子外但在+outsidewidth内时,根据距离由远及近0°->90°改变倒地的角度。

 

此处将90÷OutSideWidth得到每1单位OutSideWidth对应多少°,|向量OB|(即草竖直方向离车子中心的距离)减去CarLong得到草离车子边的距离L,然后L去乘上面得到的等分,得到L对应的角度,因为初始的角度时90°,即有这样的关系,草离车子边的距离L:OutSideWidth->0时,草的角度∠:0->9090再减去乘出来度数可得到草应旋转的度数,然后除以360可以得到需要的浮点数。

 

 

此处还可以根据车子的前进后退,让草分别做出往前旋转还是往后旋转,在前面的MaterialParameterCollection中新增一个CarForwardSpeed,并在EventTick下实时获取车子的速度方向,然后根据CarForwardSpeed的值传+360-360到上上图中。

 

 

判断草水平方向离车子边的如下图,同理。

 

 

完成后,大体结构如下。

 

 

如果需要HLSL代码,可以点击window->HLSL Code

 

 

到此就完成了。

以上是关于虚幻4 在Material中如何实现 车子压倒草的功能的主要内容,如果未能解决你的问题,请参考以下文章

虚幻4引擎可以建模吗?如果可以建模,如何建?用虚幻4引擎做游戏,模型是从哪里来的?用maya还是3dmax?

虚幻4 汽车行驶如何产生扬尘和溅水的效果

虚幻4如何实时显示人物当前坐标

虚幻4蓝图虚拟机剖析

如何在虚幻引擎 4 中正确编辑可扩展性设置/组? “覆盖”默认的

虚幻4垃圾回收剖析