unitymask迷雾 网络同步如何实现地图迷雾

2添加评论分享收藏感谢收起赞同 添加评论分享收藏感谢收起写回答游戏蛮牛学习群(纯技术交流,不闲聊):
扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
当前位置: &
查看: 4797|回复: 5
Unity3D学习笔记(四)天空、光晕和迷雾
16排名1昨日变化主题帖子积分
在线时间2266 小时
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
才可以下载或查看,没有帐号?
六年前第一次接触《魔兽世界》的时候,被其绚丽的画面所折服,一个叫做贫瘠之地的地方,深深印在我的脑海里。当时在艾泽拉斯大陆还不能使用飞行坐骑,试想一下孤身一人在银色的月光下赶路,可能还有你的战斗小伙伴,静谧的夜晚,皎洁的月光,一起走过了六年……即便是现在回想起来,浮现在脑海中的不是T456,而是十字路口的夜空。
1.jpg (54.62 KB, 下载次数: 3)
15:12 上传
回到正题,在Unity中要创建这样的效果并不困难,用专业一点的术语讲就是只需要创建一个天空盒,并给予它天空纹理即可。通俗一点来讲,就是在我们的前面几章创建的地形四周罩上一个立方体盒,并把盒子上面添上星空的照片就搞定了。有软件可以将魔兽世界的素材提取出来,然后加以利用到我们自己的游戏中。不过这一章我并不准备讲述这些,因为主题是为了把天空盒和镜头光晕的知识点整理一下,如果有时间,我会另写一篇关于如何使用强大的”Wow Model Viewer”来导出魔兽世界的模型、贴图等素材,并导入到Unity中。其实具体操作并不困难,心急的朋友们可以去google code下载这个软件:http://code.google.com/p/wowmodelviewer/downloads/listUnity自带了好几种天空盒,从白天到黄昏再到夜晚,拿来做场景练习已经完全够用了。要使用天空盒素材,只需要导入Skyboxes素材包即可(至于如何导入可以参考我之前的笔记,每次都重复一遍略显蛋疼^_^)。导入成功后可以在项目资源面板的“Standard Assets-&Skyboxes”目录下看到好多天空盒素材,Unity已经把盒子都造好了,我们直接拿来用就OK,非常人性化。接下来要把天空盒素材添加到游戏场景里,有两种添加天空盒的方法,这里先写比较容易理解的一种,另外一种将在以后写预设和组件的时候再解释。点击主菜单“Edit(编辑)-&Render Settings(渲染设置)”,检视面板视图里就会出现渲染设置选项了,注意有个Skybox Material(天空盒材质)选项,点击它右边的小圆圈,就会弹出选择天空盒材质的对话框。单击任意一个材质球,设计视图中会立即提供预览,双击则表示确认使用,相当便捷。
2.jpg (317.29 KB, 下载次数: 1)
15:13 上传
光这样是不够的,还记得之前添加的”线性光”吗?没错,就是那个“无限远、无限大类似于太阳的手电筒”^_^。它现在正静静地躺在层次面板中默默地燃烧自己,照亮世界,它不叫雷锋,它的名字叫做Directional light。这个名字有点拗口,选中它并按快捷键F2修改,换成Sun,就把它当作游戏里的太阳。细心的朋友会发现,太阳光的方向和天空盒上那个假的太阳的方向不一定会一致,可能导致太阳的位置和影子的位置有悖现实,所以必须手动调整,让它们重合。这里提供一种便捷的方法,首先在设计视图中拖动视角,让镜头中心对准天空盒上的太阳,然后在渲染设置中临时将天空盒设置为无(为了方便调整Sun的角度,否则天空盒太亮看不清楚)。然后选中Sun并使用旋转工具(快捷键E),将光线的方向正对自己,然后再将天空盒恢复即可。这样一来就不会闹太阳和影子在同一个方向的笑话了。
3.jpg (17.19 KB, 下载次数: 0)
15:13 上传
玩过摄影的朋友应该都有这么个常识,当把镜头着阳光时,可能会出现一个或者多个七彩光环的光晕现象。百度一下光晕,发现全是关于某个游戏的@_@,好不容易找到张照片,就委屈一下大妈您嘞。右上角就是传说中的光晕啦。导入Unity自带的素材包“Light Flares(闪光)”,选中线性光“Sun”,在Sun的检视面板中找到Flare属性,选择一个光晕图片(我选的是50 mm Zoom),当当当当~看看天上的太阳,是不是耀眼多了?
4.jpg (139.31 KB, 下载次数: 6)
15:16 上传
5.jpg (450.36 KB, 下载次数: 0)
15:14 上传
完成光晕之后顺便把迷雾之类的设置也了解一下吧,所谓“欲穷千里目,更上一层楼”,放在当今城市里已经不太合适了。因为污染呀,各种细小的粉尘漂浮在空气中,平时可能难以察觉,但是当举目远眺的时候就会发现远处根本就是一片迷茫嘛,跟大雾天一样的。在Unity的渲染设置中可以方便地调节这种迷雾的效果,甚至可以改变颜色和浓度等等:Fog(是否启用迷雾效果)Fog Color(迷雾的颜色)Fog Mode(迷雾模式) 可以选择“Linear(线性)”、“Exponential(指数性)”、“Exp2(指数性2)”三种渲染模式,具体动手尝试一下即可,差别不是很大。Fog Density(迷雾浓度)Linear Fog Start(线性迷雾起始距离)Linear Fog End(线性迷雾终止距离) 当选择线性的迷雾模式时,这两个参数表示了相对于镜头的迷雾的范围。在这个范围内迷雾的浓度会被平均化,也就是说当范围很小的时候,远处的物体会很清晰,近处的物体反倒一点都看不见。Ambient Light(环境光) 调节这个颜色会影响到整个游戏场景的光线,比如调成粉红色的话……就好暧昧啊 哈哈。Skybox Material(天空盒材质)Halo Strength(光环强度,没弄明白)Flare Strength(光晕强度)Halo Textrue(光环贴图,没弄明白)Spot Cookie(光斑?没弄明白)
6.jpg (380.71 KB, 下载次数: 0)
15:16 上传
最后上张效果图,骄阳似火闷得慌啊哈哈~看来下一章非得加点水不可了:)
作者:黄旭杨 http://huangxuyang.cn/archives/23
如何深入学习;unity3d 天空;unity改变物体的位置;unity 天空盒添加;unity3d下载软件;unity导入模型贴图;unity遍 物体;unity 中心点 设置;unity纹理贴图;unity创建一个物体;unity 天空盒 移动;unity3d天空盒子;unity 旋转模型;unity怎么改变材质;unity限制旋转角度范围;unity如何导入unity场景下载;unity3d 创建材质球;unity拖动物体移动;unity3d如;怎么学习unity3d;如何学习unity3d;unity3d的学习总结;unity3d 学习;unity3d学习需要什么;unity3d深入学习;unity3d如何学习;unity3d中天空;unity改变物体位置;unity添加天空盒;下载unity3d软件;unity 模型贴图导入;unity遍历物体;unity 设置中心;unity贴图纹理;unity适用的纹理图;unity 创建 物体;unity怎么加天空盒;unity天空盒;unity3d 5 天空盒子;模型旋转unity 模型旋转不正常;unity模型怎么旋转;unity模型自己旋转;unity 模型旋转;unity改变材质;unity 旋转角度限制;unity左右角度旋转;unity 导入unity在哪儿下载场景;unity skybox 无法使用;unity 5unity3d如何创建材质球;unity拖动物体;unity3d 创建材质;unity如何导入资源包;unity怎么导入资源包;unity中材质和贴图;unity3d旋转角度;unity3d旋转角度对比;unity3d 最小旋转角度;unity3d 旋转一定角度;unity 下载图片;unity3d怎么做地形;unity 弹出对话框;unity对话框;unity3d 5unity快捷键设置在哪;unity 设置快捷键;unity材质 调;unity修改后导出;unity如何创建地形;unity3d 如何添加材质;unity material 多个;unity软件下载;unity怎么导入场景;unity3d 5.3.3渲染设置;unity 多场景编辑;unity 多场景 选择;unity 点击模型;unity 游戏菜单;unity材质修改;unity导入包;unity 5unity 5.3unity中心旋转;unity加天空;unity怎么加天空;unity 天空;unity3d 添加纹理;unity影子;unity影子没有了;unity添加材质球;unity设计模式;ambient light unity 5;unity 5unity天空盒子;unity怎么导入素材;怎么把素材导入unity3d遍 物体;unity导入项目;unity如何导入项目;unity项目导入打开;unity 创建场景;镜头光晕unity3d;场景渲染unity 提取模型;unity场景贴图;unity3d资源包下载;unity导出资源;unity 两个物体的距离;unity3d 地形选项;unity方向键;unity 城市;unity设置天空盒;unity 物体方向;unity3d导入资源包;render settings unity 5.0;unity如何预渲染;unity3d 导入纹理
每日推荐:
蛮牛相关业务合作(市场合作/项目需求/人才招聘)联系-崇慕 QQ:
72079/5000排名<font color="#FF昨日变化1主题帖子积分
日久生情, 积分 2079, 距离下一级还需 2921 积分
日久生情, 积分 2079, 距离下一级还需 2921 积分
蛮牛币4982
在线时间240 小时
学习了。。
每日推荐:
72721/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 2721, 距离下一级还需 2279 积分
日久生情, 积分 2721, 距离下一级还需 2279 积分
蛮牛币2445
在线时间608 小时
作为扫盲贴感觉还不错
每日推荐:
5629/1000排名<font color="#FF昨日变化3主题帖子积分
熟悉之中, 积分 629, 距离下一级还需 371 积分
熟悉之中, 积分 629, 距离下一级还需 371 积分
蛮牛币1047
在线时间156 小时
楼主光晕和天空盒太阳不在同一个方向怎么改???就是sun的方向和天空盒假太阳不在听一个方向
每日推荐:
5629/1000排名<font color="#FF昨日变化3主题帖子积分
熟悉之中, 积分 629, 距离下一级还需 371 积分
熟悉之中, 积分 629, 距离下一级还需 371 积分
蛮牛币1047
在线时间156 小时
楼主求回复啊。真的不懂
每日推荐:
3191/300排名<font color="#FF昨日变化3主题帖子积分
偶尔光临, 积分 191, 距离下一级还需 109 积分
偶尔光临, 积分 191, 距离下一级还需 109 积分
在线时间40 小时
这个教程很喜欢支持支持
每日推荐:
蛮牛论坛干货区作者
社区QQ达人
使用QQ帐号登录论坛的用户
连续签到30天一  效果图
  先上效果图吧,这是为了吸引到你们的ヽ(?????)??
战争迷雾效果演示图
战争迷雾调试界面演示图
  由于是gif录制,为了压缩图片,帧率有点低,实际运行时,参数调整好是不会像这样一卡一顿的。
二  战争迷雾概述
  战争迷雾一般用于Startcraft等RTS类型游戏,还有就是War3等Moba类型游戏,主要包括三个概念:未探索区域、已探索区域、当前视野。
  1)未探索区域:一般展示为黑色区域,像星际争霸这样的游戏,开局时未探索区域一般是暗黑的,只有地图上的原始晶体矿产能够被看到,敌人建筑、角色等都不暴露。
  2)已探索区域:一般显示为灰色区域,已探索表示某块区域曾经被你的视野覆盖过,星际争霸中已探索的区域会保留你当时视野离开时该区域的建筑状态,所以可以看到敌人的建筑。
  3)当前视野:一般全亮,视野范围内除了隐身单位等特殊设定,所有的建筑、角色、特效等都是可见的,视野一般锁定在可移动角色或者特定魔法上面,会随着角色的移动而移动,随着魔法的消失而消失。
三  实现原理
  战争迷雾的实现方式大体上可以分为两个步骤:贴图生成、屏幕渲染。
3.1  贴图生成
  贴图的生成有两种方式:
  1)拼接法:
    使用类似地图拼接的原理去实现,贴图如下:
战争迷雾拼接贴图
    这种方式个人认为很不靠谱,局限性很大,而且迷雾总是会运动的,在平滑处理这点上会比较粗糙,不太自然。这里不再赘述它的实现原理。
  2)绘制法:绘制法和使用的地图模型有很大关系,一般使用的有两种模型:一个是正方形地图,另外一个是六边形地图。六边形地图示例如下:
战争迷雾六边形地图贴图
    原理简单直白,使用正方形/者六边形划分地图空间,以正方形/六边形为单位标记被探索过和当前视野区域。这里探索过的区域是棱角分明的,可以使用高斯模糊进行模糊处理。一般来说,正方形/六边形边长要选择合适,太长会导致模糊处理效果不理想,太短会导致地图单元格太多,全图刷新消耗增大。另外说一句,战争迷雾的地图和战斗系统的逻辑地图其实是可以分离的,所以两者并没有必然联系,你可以单独为你的战争迷雾系统选择地图模型。我也建议你不管是不是同一套地图,实现时都实现解耦。
3.2  屏幕渲染
  得到如上贴图以后,就可以渲染到屏幕了,渲染方式一般来说有3种:
  1)屏幕后处理:在原本屏幕显示图像上叠加混合战争迷雾贴图。
  2)摄像机投影:使用投影仪进行投影,将战争迷雾投影到世界空间。
  3)模型贴图:使用一张覆盖整个世界空间的平面模型来绘制战争迷雾贴图。
  不管你选择使用哪一种方式,在这一步当中都需要在Shader里进行像素级别的平滑过渡。从上一个时刻的贴图状态过渡到当前时刻的贴图状态。
四  代码实现
  原理大致上应该是清楚了,因为这个系统的设计原理实际上也不算是复杂,下面就一些重要步骤给出代码实现。这里实践的时候采用的是正方形地图,模型贴图方式。正方形地图模型不管是模糊处理还是Shader绘制都要比六边形地图简单。正方形贴图Buffer使用Color32的二维数组表示,根据位置信息,每个正方形网格会对应一个Color32数据,包含颜色值和透明度,能够很好的进行边缘平滑效果。
<span style="color: # // Color buffers -- prepared on the worker thread.
<span style="color: # protected Color32[] mBuffer0;
<span style="color: # protected Color32[] mBuffer1;
<span style="color: # protected Color32[] mBuffer2;
  这里使用了3个Buffer,是因为图像处理是很耗时的,所以为它单独开辟了线程去处理,为了线程同步问题,才增设了Buffer,关于线程这点稍后再说。
4.1  刷新贴图Buffer
  贴图Buffer需要根据游戏逻辑中各个带有视野的单位去实时刷新,在正方形地图模型中,是根据单位当前位置和视野半径做圆,将圆内圈住的小正方形标记为探索。
1 void RevealUsingRadius (IFOWRevealer r, float worldToTex)
// Position relative to the fog of war
Vector3 pos = (r.GetPosition() - mOrigin) * worldToT
float radius = r.GetRadius() * worldToTex - radiusO
// Coordinates we'll be dealing with
int xmin = Mathf.RoundToInt(pos.x - radius);
int ymin = Mathf.RoundToInt(pos.z - radius);
<span style="color: #
int xmax = Mathf.RoundToInt(pos.x + radius);
<span style="color: #
int ymax = Mathf.RoundToInt(pos.z + radius);
<span style="color: #
<span style="color: #
int cx = Mathf.RoundToInt(pos.x);
<span style="color: #
int cy = Mathf.RoundToInt(pos.z);
<span style="color: #
<span style="color: #
cx = Mathf.Clamp(cx, <span style="color: #, textureSize - <span style="color: #);
<span style="color: #
cy = Mathf.Clamp(cy, <span style="color: #, textureSize - <span style="color: #);
<span style="color: #
<span style="color: #
int radiusSqr = Mathf.RoundToInt(radius * radius);
<span style="color: #
<span style="color: #
for (int y = y & ++y)
<span style="color: #
<span style="color: #
if (y & -<span style="color: # && y & textureSize)
<span style="color: #
<span style="color: #
int yw = y * textureS
<span style="color: #
<span style="color: #
for (int x = x & ++x)
<span style="color: #
<span style="color: #
if (x & -<span style="color: # && x & textureSize)
<span style="color: #
<span style="color: #
int xd = x -
<span style="color: #
int yd = y -
<span style="color: #
int dist = xd * xd + yd *
<span style="color: #
<span style="color: #
// Reveal this pixel
<span style="color: #
if (dist & radiusSqr) mBuffer1[x + yw].r = <span style="color: #5;
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # }
  第一个参数包含了视野单位的信息,包括位置和视野半径;第二个参数为世界坐标到贴图坐标的坐标变换,R通道用于记录视野信息。
4.2  贴图Buffer模糊
  每次贴图刷新以后,进行一次贴图模糊处理。
1 void BlurVisibility ()
for (int y = <span style="color: #; y & textureS ++y)
int yw = y * textureS
int yw0 = (y - <span style="color: #);
if (yw0 & <span style="color: #) yw0 = <span style="color: #;
<span style="color: #
int yw1 = (y + <span style="color: #);
<span style="color: #
if (yw1 == textureSize) yw1 =
<span style="color: #
<span style="color: #
yw0 *= textureS
<span style="color: #
yw1 *= textureS
<span style="color: #
<span style="color: #
for (int x = <span style="color: #; x & textureS ++x)
<span style="color: #
<span style="color: #
int x0 = (x - <span style="color: #);
<span style="color: #
if (x0 & <span style="color: #) x0 = <span style="color: #;
<span style="color: #
int x1 = (x + <span style="color: #);
<span style="color: #
if (x1 == textureSize) x1 =
<span style="color: #
<span style="color: #
int index = x +
<span style="color: #
int val = mBuffer1[index].r;
<span style="color: #
<span style="color: #
val += mBuffer1[x0 + yw].r;
<span style="color: #
val += mBuffer1[x1 + yw].r;
<span style="color: #
val += mBuffer1[x + yw0].r;
<span style="color: #
val += mBuffer1[x + yw1].r;
<span style="color: #
<span style="color: #
val += mBuffer1[x0 + yw0].r;
<span style="color: #
val += mBuffer1[x1 + yw0].r;
<span style="color: #
val += mBuffer1[x0 + yw1].r;
<span style="color: #
val += mBuffer1[x1 + yw1].r;
<span style="color: #
<span style="color: #
c = mBuffer2[index];
<span style="color: #
c.r = (byte)(val / <span style="color: #);
<span style="color: #
mBuffer2[index] =
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
// Swap the buffer so that the blurred one is used
<span style="color: #
Color32[] temp = mBuffer1;
<span style="color: #
mBuffer1 = mBuffer2;
<span style="color: #
mBuffer2 =
<span style="color: # }
  用周围的8个小正方形进行了加权模糊,这里并没有像高斯模糊那样去分不同的权重。
4.3  Buffer运用到贴图
  Buffer一旦处理完毕,就可以生成/刷新贴图供屏幕显示用,不管你使用上述方式中的哪一种,在Shader执行贴图采样时,这张贴图是必须的。
1 void UpdateTexture ()
if (!enableRender)
if (mTexture == null)
<span style="color: #
// Native ARGB format is the fastest as it involves no data conversion
<span style="color: #
mTexture = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false);
<span style="color: #
<span style="color: #
mTexture.wrapMode = TextureWrapMode.C
<span style="color: #
<span style="color: #
mTexture.SetPixels32(mBuffer0);
<span style="color: #
mTexture.Apply();
<span style="color: #
mState = State.B
<span style="color: #
<span style="color: #
else if (mState == State.UpdateTexture)
<span style="color: #
<span style="color: #
mTexture.SetPixels32(mBuffer0);
<span style="color: #
mTexture.Apply();
<span style="color: #
mBlendFactor = 0f;
<span style="color: #
mState = State.B
<span style="color: #
<span style="color: # }
4.4  屏幕渲染
  主要是做两件事情:CS测在OnWillRenderObject给Shader传递参数;另外就是Shader中根据最新的战争迷雾贴图和战争迷雾颜色设定执行平滑过渡。
1 void OnWillRenderObject()
if (mMat != null && FOWSystem.instance.texture != null)
mMat.SetTexture("_MainTex", FOWSystem.instance.texture);
mMat.SetFloat("_BlendFactor", FOWSystem.instance.blendFactor);
if (FOWSystem.instance.enableFog)
mMat.SetColor("_Unexplored", unexploredColor);
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
mMat.SetColor("_Unexplored", exploredColor);
<span style="color: #
<span style="color: #
mMat.SetColor("_Explored", exploredColor);
<span style="color: #
<span style="color: # }
  其中blendFactor是过渡因子,会在Update中根据时间刷新,用于控制Shader的平滑过渡过程。
<span style="color: # fixed4 frag(v2f i) : SV_Target
<span style="color: # {
<span style="color: #
half4 data = tex2D(_MainTex, i.uv);
<span style="color: #
half2 fog = lerp(data.rg, data.ba, _BlendFactor);
<span style="color: #
half4 color = lerp(_Unexplored, _Explored, fog.g);
<span style="color: #
color.a = (<span style="color: # - fog.r) * color.a;
<span style="color: #
<span style="color: # }
<span style="color: # ENDCG
  data是贴图,rg和ba通道是连续的两个战争迷雾状态的数据,其中r通道表示当前是否可见(是否在视野内),g通道表示是否被探索过(大于0则探索过)。
4.5  多线程
  本例当作,贴图Buffer的刷新和模糊处理是在子线程处理的;而Buffer运用到贴图在主线程中;屏幕渲染在GPU当作。所以Unity主线程只是在不停地刷新贴图,而贴图Buffer和模糊处理这两个很耗性能的操作全部由子线程代劳,这就是标题所说的“高性能”原因所在,即使子线程每次的处理周期达到30毫秒,它依旧不会影响到游戏帧率。
  多线程编程必然要考虑的一点是线程同步,此处主要的问题有两个:
    1)工作子线程输入:刷新贴图Buffer需要Unity主线程(或者游戏逻辑主线程)中游戏中的视野体数据(位置、视野半径)
    2)工作子线程输出:由最新的游戏逻辑数据刷新贴图Buffer,以及进行贴图Buffer混合以后,要在Unity主线程将数据运用到贴图
  工作子线程的输入同步问题稍后再说,这里说下第二步是怎样去保证同步的,其大致步骤是:
    1)设置3个状态用于线程同步:
<span style="color: # public enum State
<span style="color: # {
<span style="color: #
<span style="color: #
NeedUpdate,
<span style="color: #
UpdateTexture,
<span style="color: # }
    2)NeedUpdate表示子线程需要处理贴图Buffer,这个状态的设置是由设定的刷新频率和实际处理时的刷新速度决定的:
1 void ThreadUpdate()
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
while (mThreadWork)
if (mState == State.NeedUpdate)
sw.Reset();
<span style="color: #
sw.Start();
<span style="color: #
UpdateBuffer();
<span style="color: #
sw.Stop();
<span style="color: #
mElapsed = <span style="color: #.001f * (float)sw.ElapsedM
<span style="color: #
mState = State.UpdateT
<span style="color: #
<span style="color: #
Thread.Sleep(<span style="color: #);
<span style="color: #
<span style="color: # #if UNITY_EDITOR
<span style="color: #
Debug.Log("FOW thread exit!");
<span style="color: # #endif
<span style="color: # }
    3)子线程会将Unity主线程(或者游戏逻辑线程)提供的最新视野状态数据刷新到贴图Buffer1的R通道,然后使用Buffer2做临时缓存对Buffer1执行模糊,模糊以后交换双缓存,最后将Buffer1的rg通道拷贝到Buffer0,所以Buffer0的ba和rg通道分别存放了上一次刷新和当前本次刷新的战争迷雾状态数据,Buffer0运用到贴图以后由Shader在这两个状态间进行平滑过渡。
1 void RevealMap ()
for (int index = <span style="color: #; index & mTextureSizeS ++index)
if (mBuffer1[index].g & mBuffer1[index].r)
mBuffer1[index].g = mBuffer1[index].r;
<span style="color: # }
<span style="color: #
<span style="color: # void MergeBuffer()
<span style="color: # {
<span style="color: #
for (int index = <span style="color: #; index & mTextureSizeS ++index)
<span style="color: #
<span style="color: #
mBuffer0[index].b = mBuffer1[index].r;
<span style="color: #
mBuffer0[index].a = mBuffer1[index].g;
<span style="color: #
<span style="color: # }
    4)子线程工作处理完以后设置UpdateTexture状态,通知Unity主线程:“嘿,饭已经做好了,你来吃吧!”,Unity主线程随后将Buffer0缓存运用到贴图。
1 void Update ()
if (!enableSystem)
if (textureBlendTime & 0f)
<span style="color: #
mBlendFactor = Mathf.Clamp01(mBlendFactor + Time.deltaTime / textureBlendTime);
<span style="color: #
<span style="color: #
else mBlendFactor = 1f;
<span style="color: #
<span style="color: #
if (mState == State.Blending)
<span style="color: #
<span style="color: #
float time = Time.
<span style="color: #
<span style="color: #
if (mNextUpdate & time)
<span style="color: #
<span style="color: #
mNextUpdate = time + updateF
<span style="color: #
mState = State.NeedU
<span style="color: #
<span style="color: #
<span style="color: #
else if (mState != State.NeedUpdate)
<span style="color: #
<span style="color: #
UpdateTexture();
<span style="color: #
<span style="color: # }
    5)UpdateTexture执行完毕以后,进入Blending状态,此时Unity主线程要等待下一次更新时间,时间到则设置NeedUpdate状态,通知子线程:“嘿,家伙,你该做饭了!”。
4.6  模块分离
  上面讲到贴图Buffer刷新子线程和Unity渲染主线程的同步与临界资源的互斥,现在来说说Unity主线程(游戏逻辑主线程)与贴图Buffer刷新子线程的同步。
  1)使用互斥锁同步视野体生命周期
1 // Revealers that the thread is currently working with
2 static BetterList&IFOWRevealer& mRevealers = new BetterList&IFOWRevealer&();
4 // Revealers that have been added since last update
5 static BetterList&IFOWRevealer& mAdded = new BetterList&IFOWRevealer&();
7 // Revealers that have been removed since last update
8 static BetterList&IFOWRevealer& mRemoved = new BetterList&IFOWRevealer&();
<span style="color: # static public void AddRevealer (IFOWRevealer rev)
<span style="color: # {
<span style="color: #
if (rev != null)
<span style="color: #
<span style="color: #
lock (mAdded) mAdded.Add(rev);
<span style="color: #
<span style="color: # }
<span style="color: #
<span style="color: # static public void RemoveRevealer (IFOWRevealer rev)
<span style="color: # {
<span style="color: #
if (rev != null)
<span style="color: #
<span style="color: #
lock (mRemoved) mRemoved.Add(rev);
<span style="color: #
<span style="color: # }
    这个应该没啥好说的,子线程在处理这两个列表时同样需要加锁。
  2)视野体使用IFOWRevelrs接口,方便模块隔离和扩展。同步问题这里采用了一种简单粗暴的方式,由于战争迷雾属于表现层面的东西,即使用于帧同步也不会有问题。
1 public interface IFOWRevealer
// 给FOWSystem使用的接口
bool IsValid();
Vector3 GetPosition();
float GetRadius();
// 给FOWLogic使用的接口,维护数据以及其有效性
void Update(int deltaMS);
<span style="color: #
void Release();
<span style="color: # }
    继承IFOWRevealer接口用来实现各种不同的视野体,本示例中给出了角色视野体与临时视野体的实现,其它视野体自行根据需要扩展。
五  其它说明
  其它还有FOWlogic模块用来隔离FOW系统和游戏逻辑,FOWRender用于fow渲染等,不再一一说明,自行阅读代码。
  有关六边形地图的战争迷雾实现稍作变通应该做起来问题也不是太大,相关信息可以参考:和。
  这一系列文章都有译文,英文不好的同学参考:和。
  然后,本演示工程的核心算法是由移植而来的,该插件由NGUI作者发布,不过已经被我大幅修改。
六  工程下载
  最后附上本演示工程的GitHub地址:。
阅读(...) 评论()}

我要回帖

更多关于 unitymask迷雾 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信