常见游戏里的效果
最常见的是LOL的
红警的大家也不陌生
尝试实现思路
主要思路就是用一个黑色半透遮罩遮住地图,然后根据游戏单位的位置,设置没有战争迷雾的区域。 底层是用一个RenderTarget来表示迷雾,透明地方就是有视野的区域,默认不透明的地方就是无视野区域
核心步骤1 迷雾表现
这个遮罩要满足: 1 半透明,像LOL那样能看到地图 2 在单位脚下,不然camera的角度变化时候,透视关系不对。
实现思路就是创建一个plane,使用新建的材质FogOfWarMaterial,在这材质里使用之前提到的RT
同时为了让这个遮罩在单位脚下(地面),又能渲染在所有单位的前面,要在这个材质里把深度测试关掉:
这样到这一步就得到了一个全地图的半透迷雾遮罩:
核心步骤2 有视野区域的表现
根据上面的材质逻辑,一个区域的遮罩是否透明是根据RT的R通道的值来决定的 所以只需要在有视野的地方把RT设为红色就行 运行时修改RT的值可以用这个节点:
用到了一个新建的材质:RevealMaterial 这个材质里用SphereMask实现了一个“点亮”的圆效果,同时根据传入的参数(UV坐标)来确定位置
这时我们在把(0,0)当作参数传入材质,并且把这个材质画到RT上,就可以得到目前的效果:
核心步骤3 获取单位的uv坐标
直接贴图吧,在tick里把单位actor和迷雾所在的plane做LineTrace检测,检测到之后用FindCollisionUV获取UV坐标,这个就是上一节的材质要用的参数。 当然在此之前要在项目设置里添加新的碰撞通道Fog,然后对单位actor和plane都要设置对Fog的碰撞检测。此外这里没有考虑性能,每帧都做了,实际使用中可以考虑更好的更新方式。
核心步骤4 更新迷雾
每次刷新迷雾时都要先清除RT:
然后将uv传入材质,然后“画到”RT上:
这样就实现了最终的效果:
单位移动时,身边区域的战争迷雾会消失。 如果想做RTS(比如红警)那种需要探索地图,且迷雾消失之后就不会再恢复的,可以不去clear RT。
可思考的点
1 战争迷雾的过渡不够自然、平滑,现在就是很僵硬的一个圆,外面的是黑的,里面的是白的。平滑可以分为两种: 空间上的:可以在PhereMask那个节点调整硬度,降低硬度可以让这个圆的界限平滑一些。 时间上的:可以做两个RT,第二个表现层的RT可以做一个随着时间的Lerp到准确的RT,这样效果过度就会很自然。 可以参考拳头的文章https://technology.riotgames.com/news/story-fog-and-war
2 性能问题 我得RT设置的很小 128 * 128 如果需要精度更大的话可能就会涉及到性能问题,清除的时机、刷新的频率都可以优化
3 这次的RT只用做了表现层,但是其实也可以当做逻辑层的数据,比如世界地图的一个GameObject可以根据坐标映射到RT上的某个像素,根据这个像素的值来判断这个GameObject是否在单位的视野里。
4 这个战争迷雾只是最简单的圆形视野,没考虑像LOL那种地形遮挡的情况,暂时没有思路,欢迎各位评论区赐教~