unity unity3d战争迷雾插件效果,求助

在U3D中实现战争迷雾
要评论请先&或者&
这方面教程真的少,楼主伟大
来瞧瞧啊啊啊
感谢分享,学习了
专业 技术很棒!!!
Mark一下 ,正在学习中
非常感兴趣,学一下谢谢分享~
看起来好高大上,好好学习学习
好东西 一定要看!
Mark一下,学习了!
不得不说,这个太棒了。9377人阅读
游戏逻辑(16)
说到战争迷雾(Fog of War, FOW), 其实还是非常普遍的一项技术, 在RPG, RTS等游戏中得到了广泛的应用&但是关于这方面的资料非常少, 经常会有人问怎么做, 所以就有了写这篇文章的想法从应用上来说, 有两种:探索范围: 通常在RPG游戏里, 用于标记走过的地图区域视野范围: 通常在RTS游戏里, 用于标记友方单位可以看到的区域当然, 在魔兽争霸3中, 两中迷雾都存在. 下面以第二种为例详细说明, 第一种看完自然就明白怎么做了好了, 既然是个可见性问题, 那么就有阻挡视线的地方和可以看到区域, 我们抽象一下, 把地图像寻路那样表示成二维格子绿点代表有视野的单位, 红色区域代表视野阻挡, 那么白色区域就是可见的, 灰色就是不可见的求解这个可以与不可见区域的问题, 其实就是一个FOV(Field of Vision, Field of View)问题, 算法上来说, 五花八门, 参见[1]有了这个可见性的区域信息, 怎么绘制到场景里呢?&既然可以表示成一个二维数组, 那么就可以把这些信息写入一张2D纹理, 然后把这个纹理投影到整个地图(不管3D还是2D, 原理一样)那么, 纹理会不会太大? 按我们的经验来讲, 一般一米一个格子的精度是完全够用的, 256x256的大小可以适用于大多数的游戏如果嫌锯齿太难看, 做个模糊就行了. 3D游戏中更是可以在shader中针对视野内和视野外使用不同的着色方式(比如去色)原理其实看起来很简单, 这也是多数帖子和文章可以提到的, 但是实际做下来, 性能还是比较棘手的一个问题目前来说, 我们在此基础上做了一些优化:降低更新频率如果游戏是30FPS的, 那么其实没有必要每帧都去计算这个可见性. 经验值的话, 0.5秒一次差不多由此带来的跳变问题, 可以保存相邻再次计算的结果, 写入迷雾纹理的两个通道, 在shader中按时间进行插值过渡&大量移动单位和大视野不动单位[2][3]这个用个循环暴力计算显然不现实, 除非你地图很小-_-. 所以, 优化思路就是针对移动的单位重新计算, 针对不动的单位只算一次首先, 我们可以用坐标(X,Y)和视野半径(R)三个值确定出一个唯一值K代表一个提供视野的单位U对于每帧新加入(K当前不存在)的U, 定义其生命周期L=MAX. 其余的就对U的L进行递减移除L&=0的U. 针对于L=MAX的, 计算其可见的格子, 如果可见, 则格子的计数C加1每个格子的可见计数C&0的表示可见, 否则就是不可见, 然后更新到纹理上对于0&L&MAX的单位U全部不用计算, 所以不动的单位就不用更新预计算FOV如果视野阻挡不会变化的话, 可以针对每个点计算其最大视野范围的可见性信息, 缓存起来如果用1bit表示每个格子, 最大视野范围20, 地图大小256x256个格子的话, 所需要的内存空间为41x41x256x256bit=13.13MB, 如果再剔除掉视野阻挡内的点, 应该更小另外, 对于小地图, 正好可以把迷雾纹理与背景直接混合, 做到二次利用对于探索范围的表示, 其实只要在格子的计数器上做点手脚就好了YY一下, 3D的体积迷雾是不是可以用Volumn纹理实现:)参考资料[1][2][3][4][5]
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1236192次
积分:15725
积分:15725
排名:第488名
原创:238篇
转载:74篇
译文:28篇
评论:897条
文章:42篇
阅读:79478
(1)(1)(1)(1)(3)(1)(4)(1)(1)(1)(2)(1)(1)(1)(2)(1)(4)(2)(2)(1)(1)(2)(1)(3)(4)(1)(1)(2)(1)(1)(1)(1)(1)(1)(1)(2)(5)(2)(1)(1)(1)(1)(5)(2)(2)(1)(1)(3)(1)(1)(1)(3)(6)(2)(2)(1)(3)(2)(3)(2)(2)(1)(2)(3)(7)(2)(5)(6)(2)(5)(1)(1)(4)(10)(6)(3)(3)(3)(8)(5)(14)(13)(10)(5)(9)(2)(2)(3)(8)(7)(6)(5)(8)(3)(3)(1)(3)(9)(7)(11)(13)(14)【Unity3D】利用Shader以及更改Mesh实现2D游戏的动态阴影效果
最近看到一个非常有趣的益智小游戏,是一个盗贼进入房子偷东西的,其实这种游戏市面上已经很多了,吸引我的是那个类似手电筒的效果,主角走到哪里,光就到哪里,被挡住的地方还有阴影。有点类似策略游戏里的战争迷雾。绞尽脑汁想了一天,终于实现类似的效果,这就给大家分享下。实现这个效果用到的技术:1.Shader实现摄影机透明穿透效果(光照的实现)2.代码里动态改变mesh(阴影形状的实现)废话不多说,动手。--------------------------------------------------------------------------------------------仔细观察可以看出,没被光照到的地方是灰色的,照到的地方是彩色的,而且被光照到的地方,不仅能显示出被光照到后的效果(彩色地面),还能显示出一些物品,比如钥匙,敌人等。由此可推测,这场景应该是两个层组成的,一个层在下,是彩色地面以及敌人等要隐藏的物品,另一个层在上,是没有被照亮的时候的地图,然后根据光线进行裁剪,光线能到达的地方,就把上层该地方裁剪掉,露出底下部分,从而实现&照亮&的效果。因此我们先按照这种思路搭载场景:1.题目说的是2D游戏,我这里弄成3D的,其实都所谓,最终的视觉是俯视的,其实也跟2D一样,这里弄成这个角度是方便大家识别我的层次。Up就是上层,其实什么都没有,就只有一张没被光照的时候的贴图(我这里偷懒直接用一片灰色代替了)Down就是下层,这里把几乎所有元素都放满了,玩家,敌人,墙等2.接下来将各种类型的对象放到相应的层里去,方便相机筛选(这里的层跟上面提到的层不一样,这里的层是Unity里的定义)&这里我为了方便大家识别,为一种类型的对象设置一个层,实际操作肯定不会这样繁琐的操作的,没必要。3.创建两个相机,让它们分别显示对于的层。(先无视Mask,这个待会再讲)如果设置正确,你的显示应该跟我上图是一样的,并且把Up相机的Depth级别设置高点,让它显示在Down相机之前。4.遮挡上层,显示下层。就是这么个原理具体至于要怎么遮挡?我一开始想到的是UGUI的Mask组件,后来想想,这个Mask是固定的一张图片,那么只能显示固定的遮挡(虽然可以动态更改,但较麻烦),后来想,那么就通过网格遮挡,毕竟网格动态改变形状很容易,而且可以通过Shader轻易地实现遮挡效果。具体如下,先写这么一个Shader:Shader "Masked/Mask" {
SubShader {
// Render the mask after regular geometry, but before masked geometry and
// transparent things.
Tags {"Queue" = "Geometry+10" }
// Don't draw in the RGBA just the depth buffer
ColorMask 0
// Do nothing specific in the pass:
}}如果你懂Shader那么一眼就可以看懂它,不懂也无所谓,直接Copy进去。它其实就是让你的网格变成一个遮挡物,摄影机一看到这个网格,就会直接穿透过去,直接看到背景。然后添加一个GameObject,并添加MeshFilter以及MeshRender组件,并且赋予这个Shader,作为Mask。如果你这个Mask当前的Mesh不为空的话,你可以很直观地看到它所在的地方都不会被摄影机渲染出来,直接变成一个穿透的洞:它不仅是透明的,还是异次元洞,就算它身后的东西也显示不出来,直接就看到背景了。竟然它直接穿透到背景,那么看到看不到底层,那么我们要它何用呢?对,它只是将当期摄影机穿透到背景,所以我们将当期摄影机的Clear Flags设置为&Depth Only",这样第一个摄影机的背景将显示第二个摄影机的内容。这样就可以轻易达到我们想要的穿透。5.遮挡实现了,那么该如何实现动态光照变化呢?我这里使用的是RayCast,以主角为原点,向四周辐射一定量的射线,这样可以模拟光照,然后根据射线探测到的点组合成上面提到的遮挡物的网格。最终就达到我们想要的效果。using UnityEpublic class FOVMesh : MonoBehaviour{
public GameObject playerGameO
// 光照半径
public float range = 3;
// 光照质量,数值越低,向四周辐射的射线越多,效果越好,但性能越低
public int levelOfDetails = 1;
// 接受光照产生阴影的对象
public LayerMask[] layerM
private Vector3
private int index = 0;
private int triIndex = 0;
private int lod = 1;
private float
private GameO
private GameObject pGo;
private Vector3 worldP
private Vector3[]
private int[]
private Vector2[]
private GameObject didH
private int
// Code that runs on entering the state.
public void Start ()
go = gameO
pGo = playerGameO
mesh = new Mesh ();
go.GetComponent&MeshFilter& ().mesh =
lod = levelOfD
// 若loa为1,则共发射360条射线作为光线,则有360个顶点加个圆心
verts = new Vector3[(360 / lod) + 1];
// 每两个顶点跟圆心组成一个三角形,所以三角形的个数为定点数乘3
tris = new int[(360 / lod) * 3];
uvs = new Vector2[verts.Length];
for (int i = 0; i & layerMask.L ++i) {
mask |= layerMask [i];
// Code that runs every frame.
public void Update ()
index = 0;
triIndex = 0;
worldPos = pGo.transform.
verts [index] = worldP
for (var a=0; a&360; a += lod) {
var direction = new Vector3 (Mathf.Sin (Mathf.Deg2Rad * a), 0, Mathf.Cos (Mathf.Deg2Rad * a));
direction = direction *
if (Physics.Raycast (worldPos, direction, out hit, width, mask)) {
// 如果被射线探中,则将探测到的点作为网格的顶点
verts [index] = new Vector3 (hit.point.x, hit.point.y, hit.point.z);
// 否则将射线的末端作为网格的顶点
verts [index] = new Vector3 (direction.x + worldPos.x, worldPos.y, direction.z + worldPos.z);
// 根据网格顶点组合三角形
for (var i=1; i&(360/lod); i++) {
tris [triIndex] = 0;
tris [triIndex + 1] =
tris [triIndex + 2] = i + 1;
triIndex += 3;
tris [((360 / lod) * 3) - 3] = 0;
tris [((360 / lod) * 3) - 2] = 360 /
tris [((360 / lod) * 3) - 1] = 1;
// 网格贴图
int j = 0;
while (j & uvs.Length) {
uvs [j] = new Vector2 (verts [j].x, verts [j].z);
// 重新组合网格
mesh.Clear ();
mesh.vertices =
mesh.triangles =
mesh.RecalculateNormals ();
}最终效果如图:源码:点我下载,欢迎转载,转载请注明出处好吧,就在我写完这个帖子后的一个小时,我百度了下2D伪阴影。。。然后发现了一个神物。。。原来早就有类似的插件了,而且效果很强大,实现方法跟我这个类似,但那个还能实现光影的强弱,远处较暗近处较亮。/club/thread-.html还有一个很屌的外国人写的:/89193/
最新教程周点击榜
微信扫一扫

我要回帖

更多关于 unity 迷雾 的文章

 

随机推荐