UE4/UE5摄像头视线遮挡问题

959 阅读3分钟

如图所示,玩家再靠近建筑物时摄像头的视线会被挡住(已关闭摄像头碰撞)。

p1.png

问题演示

方法1:修改材质

        材质换成masked,写一个材质函数(具体函数内容在后面),用来计算和输出遮罩距离,最后会生成一个以摄像机为圆点的遮罩球,目标材质进入遮罩球范围会变透明。

效果:

p2.png

效果图

        这个方法还有问题,因为是按照摄像头距离来控制遮罩的,当玩家距离建筑物足够近时,依旧会被建筑物挡住。虽然可以进一步提高遮罩范围,但是没办法与多种建筑物的大小适配,甚至可能会影响其他不需要隐藏的物体。

解决办法:看后续。

材质函数: p3.png

计算距离的材质函数

后续:

        研究了一下午,虽然不能随心所欲通过代码的方式修改遮罩的形状,但是解决当前问题有了新的突破。突破点:当玩家被建筑物遮挡时,其实只需要在摄像头跟玩家之间产生一个透明的视锥(透明的圆锥)就行了。如何计算这个透明的圆锥就成了解决问题的关键(昨天想到了但是不知道如何实现)。

        众所周知:两个单位向量点乘,其实就是两个向量之间夹角的cos值。而一个圆锥内的所有点到圆锥顶点的cos值应该符合:cosθ<=x<=1的。所以,如果我需要以玩家作为中心产生一个视锥,那么按照下图所示(玩家角色在O点),我只需求得视锥内所有的点到A点的向量,和AO向量间的cos值即可。详细可以看实现截图。使用细节可以参考方法3.

p4.png

p5.png

mask实现 我将按照上图实现解释一下部分节点的含义:

PlayerToCameraVector:这个节点是一个普通的RGB节点(快捷键3),这里记录的值是玩家到摄像机的向量,因为一般玩家与摄像机的相对位置固定,可以输入一个固定的值,如果有特殊需求,可以将其变成参数值,动态传递。

Normalize:将向量归一化,将PlayerToCameraVector变成单位向量

CameraVector:获取每个顶点到摄像机的单位向量

SightSize:作为视锥角度大小的偏移值,可以动态调整这个值来改变视锥大小。

效果:

p6.png

方法1的最终效果图

这个效果个人还是比较满意的,美中不足的就是遮罩会影响建筑物的阴影,但是瑕不掩瑜。

方法2:盒体碰撞器

(大道至简)用一个盒体触发器触发碰撞事件,隐藏引用的目标物体。

效果:

p7.png

方法2的效果图 如果使用这种方式会有新的问题:建筑物消失瞬间,地面会消失。

个人分析:渲染的时候,被建筑物遮挡住的物体表面不会进行渲染(遮挡剔除),所以在那一瞬间,没有建筑物遮挡住的物体渲染数据,所以看不到地面。当建筑物消失的之后,地面变成不被遮挡,所以一瞬间渲染好了。

解决办法:(待会去查,也许不会查了)

方法3:动态材质

        这个方法需要连同方法1使用。虽然通过方法1写出了效果还可以的材质。但是,如果场景已经搭建的差不多了怎么办?总不能手动给每个模型挨个替换材质吧。如果多个模型的材质都是含有遮罩的材质,无差别透明了其他本不会遮挡玩家视线的物体怎么办?

为了解决上述的问题---动态材质了解一下。

        在方法1的实现截图中,Input和SightSize两个变量是可以通过动态传参的方式,动态修改材质的渲染效果。在这个需求中,Input控制了这个材质是否需要开启mask透明的效果。实现思路:只需给场景中需要开启mask的模型添加一个tag,然后写一个管理类就可以,通过一些节点来控制管理这些需要开启mask的模型即可。具体看下图:

p8.png

动态材质的实现

通过tag获取所有已经被标记了的模型,然后创建动态材质,并且修改Input的值。没有创建动态材质的模型,就算用的是同一个材质,但是因为参数不同所以不会开启mask。