当前位置: 首页 > news >正文

战争迷雾FogOfWar---Unity中实现

从最初的即时战略《沙丘2》开始,战争迷雾的概念开始被引入和正式提出。在沙丘中每一次新开始游戏时,玩家只能观察到自己基地及单位周围极小的范围,而绝大多数地图区域均被黑色遮盖。当他命令单位向黑暗区移动后,经过的区域会被自动打开,地图变得可见,包括该区域的地形/敌人活动情况等等。

红警战争迷雾&小地图添加

战争迷雾的实现方式是通过在地图与相机之间放置一层黑色面片,通过动态修改面片的局部透明度实现。

1.通过动态修改顶点颜色实现:

(1)准备工作:

新建一个用于迷雾的材质球

选择其材质为如下图:

并将Tint Color设置为完全的黑色

新建一个Layer命名ShadowMask(任意与存在Layer名字不同即可)

接下来新建一个Plane,将它延申到覆盖场景,改变其层的名字为shadowMask,勾选其MeshCollider的Convex(不勾选的话后边的射线检测会不起作用)

新建一个ShadowMask脚本,将脚本挂载到ShadowMask物体上,

public class ShadowMask : MonoBehaviour
{public GameObject shadowPlane;public Transform player;public LayerMask shadowMaskLayer;public float shadowRadius = 10f;private float radiusCircle { get {  return shadowRadius * shadowRadius; } }private Mesh mesh;private Vector3[] verteies; // 顶点坐标位置private Color[] verteiesColors; //顶点坐标的颜色void Start(){}void Update(){}
}

将用到的信息设置好

(2)检测玩家移动后是否能准确与迷雾网格产生碰撞

public class ShadowMask : MonoBehaviour
{public GameObject shadowPlane;public Transform player;public LayerMask shadowMaskLayer;public float shadowRadius = 10f;private float radiusCircle { get {  return shadowRadius * shadowRadius; } }private Mesh mesh;private Vector3[] verteies; // 顶点坐标位置private Color[] verteiesColors; //顶点坐标的颜色void Update(){Ray r = new Ray(player.position, player.position + Vector3.up * 100);Debug.DrawLine(player.position, player.position + Vector3.up * 100);RaycastHit hit;if (Physics.Raycast(r,out hit,1000,shadowMaskLayer,QueryTriggerInteraction.Collide)){Debug.Log(hit);}}
}

 如果一起顺利,则控制台会打印出信息

(3)更换顶点颜色

    void Update(){Ray r = new Ray(player.position, player.position + Vector3.up * 100);Debug.DrawLine(player.position, player.position + Vector3.up * 100);RaycastHit hit;if (Physics.Raycast(r,out hit,1000,shadowMaskLayer,QueryTriggerInteraction.Collide)){Debug.Log(hit);for (int i = 0; i < verteies.Length; i++){//将迷雾平面的顶点坐标变换到世界空间Vector3 v = shadowPlane.transform.TransformPoint(verteies[i]);//计算变换到世界空间下的顶点坐标与碰撞点的距离float distance = Vector3.SqrMagnitude(v - hit.point);if(distance < radiusCircle){float alpha = Mathf.Min(verteiesColors[i].a,distance/radiusCircle);verteiesColors[i].a = alpha;}}}UpdateVerteiesColors();}void UpdateVerteiesColors(){//更换顶点颜色mesh.colors = verteiesColors;}

实现效果如下图:

如果感觉效果太粗糙,可以将ShadowMask物体的顶点数增加,顶点数越多效果会更好一些

2.通过动态修改贴图像素的颜色实现:

准备工作和通过修改顶点颜色类似,只不过shadowMask的材质球需要更换shader,使用我写的这篇文章中的shader

Unity ShaderLab --- 实现局部透明-CSDN博客

然后需要动态的生成迷雾贴图,代码如下

  Texture2D fogTxtur;Color[] pixelColors;int width;int height;float shadowRadius;public FogOfWarTexture(int width,int height,float rad){this.width = width;this.height = height;this.shadowRadius = rad;fogTxtur = new Texture2D(width,height);pixelColors = new Color[width * height];for (int i = 0; i < width; i++){for (int j = 0; j < height; j++){pixelColors[i * height + j] = Color.black;}}this.SetPixels(pixelColors);}void SetPixels(Color[] colors){fogTxtur.SetPixels(pixelColors);fogTxtur.Apply();}

并且在执行中需要不断改变, 代码如下

   public void HandlerTetureColors(Vector3 point){for (int i = 0; i < this.width; i++){for (int j = 0; j < this.height; j++){if(Mathf.Abs(j - this.width/2 + point.x) < this.shadowRadius && Mathf.Abs(i- this.height/2 + point.z) < this.shadowRadius && pixelColors[i * this.height + j] == Color.black){pixelColors[i * this.height + j] = new Color(0,0,0,0);}}}this.SetPixels(pixelColors);}

 输入的point值就是玩家移动发出射线与迷雾的物体碰撞点,代码如下:

  void Update(){Ray r = new Ray(player.position, player.position + Vector3.up * 100);Debug.DrawLine(player.position, player.position + Vector3.up * 100);RaycastHit hit;if (Physics.Raycast(r, out hit, 1000, shadowMaskLayer, QueryTriggerInteraction.Collide)){Debug.Log(hit);fogTexture.HandlerTetureColors(hit.point); }}

实现效果如下图

参考链接:

Unity Shadow, Fog Walk Path (Fog of war) (youtube.com)

Unity Fog Of War Tutorial. Dynamic shader based fog of war (youtube.com)


http://www.mrgr.cn/news/77817.html

相关文章:

  • 2023AE软件、Adobe After Effects安装步骤分享教程
  • ls命令实操笔记
  • 基于Python Web的社区爱心养老管理系统设计与实现
  • 分布式系统稳定性建设-性能优化篇
  • Python爬虫案例八:抓取597招聘网信息并用xlutils进行excel数据的保存
  • JavaScript 自定义对象
  • 解决Electron拖拽窗口点击事件失效问题
  • 「Mac玩转仓颉内测版28」基础篇8 - 元组类型详解
  • 分享一下arr的意义(c基础)(必看)(牢记)
  • 爬虫重定向问题解决
  • tcp/ip异常断开调试笔记——lwip
  • Oracle 19C 安装RAC磁盘投票失败
  • Vue实训---1-创建Vue3项目
  • 【大数据学习 | Spark-Core】Spark提交及运行流程
  • 【蓝桥杯C/C++】翻转游戏:多种实现与解法解析
  • 14.C++STL1(STL简介)
  • 【蓝桥杯C/C++】深入解析I/O高效性能优化:std::ios::sync_with_stdio(false)
  • minikube单机k8s出现Listen: listen tcp :53: bind: permission denied
  • 【题解】—— LeetCode一周小结46
  • CSRF保护--laravel进阶篇
  • 【大数据学习 | Spark-Core】spark-shell开发
  • 《线性代数的本质》
  • 【计算机网络】网段划分
  • C#语言入门
  • 《Shader 入门精要》学习笔记 茵蒂克丝
  • 用python将一个扫描pdf文件改成二值图片组成的pdf文件