Unity战争迷雾(Fog Of War)

项目地址

笔记

战争迷雾在2D项目中有许多取巧的实现方式,但是在3D项目中没找到什么比较巧妙的方式.

传统的实现方式就是用一张纹理两个通道 一个表示已经探索的区域,另外一个通道表示当前视野可见的区域.

但是使用这张纹理进行迷雾绘制的方式各有各的方式,我参考到的有三种

三种方式在制作迷雾纹理上都大同小异,主要差别是在纹理的运用上

后期屏幕特效

AsehesL使用的方式是采用的后期处理

1
2
3
4
5
6
7
8
9
void OnRenderImage(RenderTexture src, RenderTexture dst)
{
if (!m_IsInitialized)
Graphics.Blit(src, dst);
else
{
m_Renderer.RenderFogOfWar(m_Camera, m_Map.GetFOWTexture(), src, dst);
}
}

UWA 战争迷雾开源库测评 之前专门做过一期评测.

对于两三年前的千元机来说 性能有些堪忧.

单Plane渲染

smilehao 采用的就是比较讨巧的办法,直接渲染到一个Plane上面.然后设置其RenderQueue为最后渲染.

Shader:

1
Tags{ "Queue" = "Transparent+151" "IgnoreProjector" = "True" "RenderType" = "Transparent" }

这种渲染方式 对于不可以自主调整 相机位置+高度 的游戏来说 是一种不错的渲染方式. 性能应该很省. 但是在能调整视角高低的情况下会穿帮

正常情况:

穿帮情况:

尤其是将相机压低以后效果会更明显.

Custom Shader

Ultimate Fog of War 实现的方式就比较传统了, 就是直接对Fow纹理进行采样了. 然后把所有的Shader重新实现一遍

我的选择


首先我要制作的游戏是 一款RTS塔防 相机效果类似于 War3. 可全局移动+俯仰角调整.

考虑到性能问题,对于AsehesL的后期渲染方式 应该会吃不消. 而smilehao的方式 当相机调整俯仰角度时候会出现穿帮. 所以我是直接采用的
Ultimate Fog of War的方式.

本来是想直接用这个插件的,不过没有太研究透这个插件 一直不知道怎么把周围迷雾调为全黑. 另外这个插件对于我这个项目来说有点太冗余了. 就自己写了一个.

Custom Shader

使用CustomShader的好处还有一个就是首先sampling Fow纹理 判断当前不可见 (fow.r > 0.9) 后续就可以直接return fixed4(0,0,0,1). 不必再继续后面的sampling+光照计算了.

对于渲染很重的项目且屏幕内大面积出现迷雾效果时候. 用这种CutstomShader来做应该会更省一些(未测试.)

不过我这个项目 大部分时候屏幕内出现迷雾的区域都不大 Shader里面用if反而是增加消耗的.所以我没加判断. 并且加入判断后在编辑器里面所有模型都是纯黑的.编辑起来也很麻烦.

线程池

参考的三个项目都使用了线程池.我也尝试的用了一下 不过没太弄懂 就放弃了.

Unity的线程池我了解到的是只能操作非Unity的API,也就是只能用于填充 FillTexture时候使用的 ColorBuffer[]

但是我的项目大量迷雾探索对象为静态的,只有一个英雄可以自由移动. 而对于静态的探索对象 我是直接Cache到一个temp array里面了

每次计算ColorBuffer时候 直接ArrayCopy的. 然后每个移动的角色自己维护一个可见范围List<>

也就是每次FillTexture时候 就是一次ArrayCopy + 少量的List ForEach.

并且我的Fow纹理不会经常变动,所以最后没有纠结使用线程的问题.

坚持原创技术分享,您的支持将鼓励我继续创作!