unity如何实现战争迷雾?思路一(代码片段)

jint-hwang jint-hwang     2023-03-20     567

关键词:

unity如何实现战争迷雾?思路一

 

断更很久了,刚好今天放假,写一个unity下实现战争迷雾的思路.

 

 

效果如下: 

 

 技术图片

 

思路如下:

建一个plane作为地面,UI中的rawimage放在最上层作为迷雾显示,cube作为主角移动.cube每次移动,将它的坐标转化为rawimage上相对位置的点,然后用texture2dsetpixel方法逐像素清除出一个区域出来.

 技术图片

 

 左下角rawimage显示小地图,有单独一个camera专门将迷雾绘制到小地图中.

 技术图片

 

具体实现:

1.新建plane,cube,分别作为地面和主角,并把场景中的Main Camera作为cube的子物体.如下设置.

 技术图片

 

 技术图片

 

 技术图片

 

 project窗口创建一个material并赋给cube方便改颜色.

技术图片

 

 技术图片

 

 

2.新建一个canvas和一个rawimage,并按如下设置.

 技术图片

 

 技术图片

 

 技术图片

 

  

3.新建一个gameobject,在它的下面,新建一个camera,新建一个canvas并在它的下面新建image,rawimage.设置如下.

 技术图片

 

 技术图片

 

 project窗口创建一个rendertexture并赋给camerarawimage.

 技术图片

 

 技术图片

 

 技术图片

 

 image用于小地图的背景框,也可忽略.

 技术图片

 

 技术图片

 

  

3.新建一个gameobject,并加上脚本.

 技术图片

 

 

4.首先,先将迷雾初始化出来.打开编辑FogOfWar脚本.定义fogRawImage,worldcanvas下的rawimage.定义fogDensity ,迷雾的像素密度,由多少个点组成.定义fogTexture,赋给fogRawImage,后续的像素颜色更改,只需对fogTexture进行.InitializeTheFog方法将迷雾初始化为黑色.

 1 public RawImage fogRawImage;
 2 
 3 public Vector2Int fogDensity = new Vector2Int(100, 100);
 4 
 5 private Texture2D fogTexture; 
 6 
 7 void Start()
 8 
 9     fogTexture = new Texture2D(fogDensity.x, fogDensity.y);
10 
11     fogRawImage.texture = fogTexture; 
12 
13     InitializeTheFog();
14 
15 
16 void InitializeTheFog()
17 
18     int pixelCount = fogDensity.x * fogDensity.y;
19     //将迷雾的默认颜色设置为黑色
20     Color[] blackColors = new Color[pixelCount];
21     for (int i = 0; i < pixelCount; i++)
22     
23       blackColors[i] = Color.black;
24     
25     fogTexture.SetPixels(blackColors); 
26 
27     fogTexture.Apply();
28 

   

5.接着,设置要消除的形状的坐标数组.定义beEliminatedShapeSize ,要消除的形状的长和宽.定义shapeLocalPosition,这个形状的点分布数组,假设中心为(0,0),后续只需要将要消除的点的坐标跟这个数组所有值相加,即可得到该点出现的形状的所有坐标.InitializeTheShape方法是初始化视野的形状,此处是矩形,如果想将视野做成椭圆形,三角形,六角形,修改InitializeTheShape中的写法然后赋给shapeLocalPosition.

 1   public Vector2Int beEliminatedShapeSize = new Vector2Int(8, 6);
 2   private Vector2Int[] shapeLocalPosition;
 3   void Start()
 4   
 5       //...
 6 
 7       InitializeTheShape();
 8   
 9 
10     void InitializeTheShape()
11     
12         int pixelCount = beEliminatedShapeSize.x * beEliminatedShapeSize.y;
13         shapeLocalPosition = new Vector2Int[pixelCount];
14 
15         int halfX = Mathf.FloorToInt(beEliminatedShapeSize.x * 0.5f);
16         int remainingX = beEliminatedShapeSize.x - halfX;
17         int halfY = Mathf.FloorToInt(beEliminatedShapeSize.y * 0.5f);
18         int remainingY = beEliminatedShapeSize.y - halfY;
19 
20         int index = 0;
21         for (int y = -halfY; y < remainingY; y++)
22         
23             for (int x = -halfX; x < remainingX; x++)
24             
25                 shapeLocalPosition[index] = new Vector2Int(x, y);
26                 index++;
27             
28         
29   

 

6.接着是在texture中消除出一个形状来.这里需要注意的是,cube是在世界坐标中,通过消除rawimage中的像素透明度来实现获得视野,所以需要将cube的坐标转换为rawimage(texture2d)相对应的点.因为texture是左下角为原点,向右为正x,向上为正y,如下图.

 技术图片

 

 所以,一种思路就是将cube的世界最左下的一点作为它的原点,然后根据cube的位置和这个原点的位置偏移量,换算成texture中相对应的点,也就是plane的左下角的坐标.下图,是从上往下看的视角.

 技术图片

定义cubeTransform,cubetransform.定义planeMeshCollider,用于获取plane的尺寸.定义planeOriginPoint,储存世界坐标中cube的假定原点.定义worldSize,地面的尺寸,也就是plane的尺寸.EliminateFog方法,获得当前cube位置的视野.

 1     public Transform cubeTransform;
 2     public MeshCollider planeMeshCollider;
 3 
 4     private Vector2 planeOriginPoint;
 5     private Vector2 worldSize;
 6     
 7     void Start()
 8     
 9         //...
10 
11         worldSize = new Vector2(planeMeshCollider.bounds.size.x, planeMeshCollider.bounds.size.z);
12      //将plane的坐标减去它尺寸的一半,即可得到它的左下角的坐标
13         planeOriginPoint = new Vector2(planeMeshCollider.transform.position.x - worldSize.x * 0.5f, planeMeshCollider.transform.position.z - worldSize.y * 0.5f);
14 
15         InitializeTheShape();
16         InitializeTheFog();
17 
18         EliminateFog();
19     
20 
21     void EliminateFog()
22     
23         Vector2 cubePos = new Vector2(cubeTransform.position.x, cubeTransform.position.z);
24      //相对假定原点的距离比例,因为是世界坐标,两个点相减有可能是负数,texture中不存在负数的坐标,所以转化为正数.
25         Vector2 originDistanceRatio = (cubePos - planeOriginPoint) / worldSize;
26         originDistanceRatio.Set(Mathf.Abs(originDistanceRatio.x), Mathf.Abs(originDistanceRatio.y));
27      //距离比例乘以密度,即可知道cube相当在texture中的点即可计算出来
28         Vector2Int fogCenter = new Vector2Int(Mathf.RoundToInt(originDistanceRatio.x * fogDensity.x), Mathf.RoundToInt(originDistanceRatio.y * fogDensity.y));
29         for (int i = 0; i < shapeLocalPosition.Length; i++)
30         
31             int x = shapeLocalPosition[i].x + fogCenter.x;
32             int y = shapeLocalPosition[i].y + fogCenter.y;
33        //因为消除迷雾的形状是比cube的位置还要大的,在最边缘的时候,消除的像素点的坐标会超出texture范围,所以超出部分忽略.
34             if (x < 0 || x >= fogDensity.x || y < 0 || y >= fogDensity.y)
35                 continue;
36 
37             fogTexture.SetPixel(x, y, Color.clear);
38         
39 
40         fogTexture.Apply();
41     

 

7.设置cube的移动控制,并在每次移动消除迷雾.这里简单写一个.

 1    public float cubeMoveSpeed = 0.1f;
 2     private void Update()
 3     
 4         if (Input.anyKey)
 5         
 6             if (Input.GetKey(KeyCode.W))
 7             
 8                 cubeTransform.position += Vector3.forward * cubeMoveSpeed;
 9             
10             else if (Input.GetKey(KeyCode.S))
11             
12                 cubeTransform.position += Vector3.back * cubeMoveSpeed;
13             
14             else if (Input.GetKey(KeyCode.A))
15             
16                 cubeTransform.position += Vector3.left * cubeMoveSpeed;
17             
18             else if (Input.GetKey(KeyCode.D))
19             
20                 cubeTransform.position += Vector3.right * cubeMoveSpeed;
21             
22 
23             EliminateFog();
24         
25 

 

8.完成后的场景结构和FogOfQar脚本设置如下.

 技术图片

 

 

9.完整代码如下:

  1 using UnityEngine;
  2 using UnityEngine.UI;
  3 
  4 public class FogOfWar : MonoBehaviour
  5 
  6     public RawImage fogRawImage;
  7     public MeshCollider planeMeshCollider;
  8     public Transform cubeTransform;
  9 
 10     public float cubeMoveSpeed = 0.1f;
 11 
 12     public Vector2Int fogDensity = new Vector2Int(100, 100);
 13     public Vector2Int beEliminatedShapeSize = new Vector2Int(8, 6);
 14 
 15     private Texture2D fogTexture;
 16 
 17     private Vector2Int[] shapeLocalPosition;
 18 
 19     private Vector2 planeOriginPoint;
 20     private Vector2 worldSize;
 21 
 22     // Start is called before the first frame update
 23     void Start()
 24     
 25         fogTexture = new Texture2D(fogDensity.x, fogDensity.y);
 26         fogRawImage.texture = fogTexture;
 27 
 28         worldSize = new Vector2(planeMeshCollider.bounds.size.x, planeMeshCollider.bounds.size.z);
 29         //将plane的坐标减去它尺寸的一半,即可得到它的左下角的坐标
 30         planeOriginPoint = new Vector2(planeMeshCollider.transform.position.x - worldSize.x * 0.5f, planeMeshCollider.transform.position.z - worldSize.y * 0.5f);
 31 
 32         InitializeTheShape();
 33         InitializeTheFog();
 34 
 35         EliminateFog();
 36     
 37 
 38     private void Update()
 39     
 40         if (Input.anyKey)
 41         
 42             if (Input.GetKey(KeyCode.W))
 43             
 44                 cubeTransform.position += Vector3.forward * cubeMoveSpeed;
 45             
 46             else if (Input.GetKey(KeyCode.S))
 47             
 48                 cubeTransform.position += Vector3.back * cubeMoveSpeed;
 49             
 50             else if (Input.GetKey(KeyCode.A))
 51             
 52                 cubeTransform.position += Vector3.left * cubeMoveSpeed;
 53             
 54             else if (Input.GetKey(KeyCode.D))
 55             
 56                 cubeTransform.position += Vector3.right * cubeMoveSpeed;
 57             
 58 
 59             EliminateFog();
 60         
 61     
 62 
 63     void InitializeTheShape()
 64     
 65         int pixelCount = beEliminatedShapeSize.x * beEliminatedShapeSize.y;
 66         shapeLocalPosition = new Vector2Int[pixelCount];
 67 
 68         int halfX = Mathf.FloorToInt(beEliminatedShapeSize.x * 0.5f);
 69         int remainingX = beEliminatedShapeSize.x - halfX;
 70         int halfY = Mathf.FloorToInt(beEliminatedShapeSize.y * 0.5f);
 71         int remainingY = beEliminatedShapeSize.y - halfY;
 72 
 73         int index = 0;
 74         for (int y = -halfY; y < remainingY; y++)
 75         
 76             for (int x = -halfX; x < remainingX; x++)
 77             
 78                 shapeLocalPosition[index] = new Vector2Int(x, y);
 79                 index++;
 80             
 81         
 82     
 83 
 84     void InitializeTheFog()
 85     
 86         int pixelCount = fogDensity.x * fogDensity.y;
 87         //将迷雾的默认颜色设置为黑色
 88         Color[] blackColors = new Color[pixelCount];
 89         for (int i = 0; i < pixelCount; i++)
 90         
 91             blackColors[i] = Color.black;
 92         
 93         fogTexture.SetPixels(blackColors);
 94 
 95         fogTexture.Apply();
 96     
 97 
 98     void EliminateFog()
 99     
100         Vector2 cubePos = new Vector2(cubeTransform.position.x, cubeTransform.position.z);
101         //相对假定原点的距离比例,因为是世界坐标,两个点相减有可能是负数,texture中不存在负数的坐标,所以转化为正数.
102         Vector2 originDistanceRatio = (cubePos - planeOriginPoint) / worldSize;
103         originDistanceRatio.Set(Mathf.Abs(originDistanceRatio.x), Mathf.Abs(originDistanceRatio.y));
104         //距离比例乘以密度,即可知道cube相当在texture中的点即可计算出来
105         Vector2Int fogCenter = new Vector2Int(Mathf.RoundToInt(originDistanceRatio.x * fogDensity.x), Mathf.RoundToInt(originDistanceRatio.y * fogDensity.y));
106         for (int i = 0; i < shapeLocalPosition.Length; i++)
107         
108             int x = shapeLocalPosition[i].x + fogCenter.x;
109             int y = shapeLocalPosition[i].y + fogCenter.y;
110             //因为消除迷雾的形状是比cube的位置还要大的,在最边缘的时候,消除的像素点的坐标会超出texture范围,所以超出部分忽略.
111             if (x < 0 || x >= fogDensity.x || y < 0 || y >= fogDensity.y)
112                 continue;
113 
114             fogTexture.SetPixel(x, y, Color.clear);
115         
116 
117         fogTexture.Apply();
118     
119 

欢迎交流.

转载注明出处.

如何在unity3d中实现战争迷雾效果

参考技术AiTweeniTween.CameraFadeToiTween.CameraFadeFrom,或者用深度摄像机,改切换画面color.a 查看详情

2d游戏平滑的迷雾战争效果

...然后就扩展一下,研究了一下战争迷雾的效果。主要是想实现类似魔兽争霸那种人物走动,然后黑色的战争迷雾随着人物的移动渐渐打开的效果。使用具有渐变透明图片作为光源来使得战争迷雾呈现出平滑的效果。本文后面介绍... 查看详情

游戏中的战争迷雾

转自:http://blog.csdn.net/xoyojank/article/details/12259161说到战争迷雾(FogofWar,FOW),其实还是非常普遍的一项技术,在RPG,RTS等游戏中得到了广泛的应用 但是关于这方面的资料非常少,经常会有人问怎么做,所以就有了写这篇文章的想法从... 查看详情

一个unity富文本插件的实现思路(代码片段)

...特点:使用占位符模式,创建新的GameObject,挂载Image组件实现图文混排主要通过正则匹配分析语法,扩展不便固定RectTransform的anchor、pivot,Text的alignment,修改排版后需要手动计算相关位置,不能实现自动布局新组件目标通过逐... 查看详情

Libgdx:“战争迷雾”效果的帧缓冲区

】Libgdx:“战争迷雾”效果的帧缓冲区【英文标题】:Libgdx:Framebufferfor"FogofWar"-Effect【发布时间】:2016-03-1808:13:52【问题描述】:我正在为Android编写一个RTS游戏,我希望在玩家的单位上添加“战争迷雾”效果。这种效果... 查看详情

透过历史迷雾进行深入探究特斯拉线圈是如何工作的?(代码片段)

...你也许看到过特斯拉线圈令人惊讶的放电展示。 它究竟如何工作的呢? 下面听听Kathy给我们讲讲特斯拉线圈每一部分是如何被发明,它的工作原理是什么。一、感应电流  故事发生在1826年,一为名叫斯特金的退... 查看详情

lycorisrecoil再现!unity实现sakana~,代码思路解析,代码开源,unity弹簧效果(代码片段)

...意起飞的,不是bug)前言我之前在看到网上有人实现了网页版的sakana,感觉超级有意思,于是动手用unity实现了一下。整个代码就弹簧效果上实现起来稍微麻烦一点,用了点数学物理的知识。Unity原本有个弹簧... 查看详情

unity-动态显示窗口制作思路(代码片段)

...们只需要制作一个动画,动画中改变Text组件的位置即可实现此效果。然而现在的问题是,不能让这个动画立刻播放,我们需要在特定的时候去播放它,并在特定的时刻停止。 那么怎么实现呢?我们可以在控制动 查看详情

游戏开发实战教你在unity中实现模型消融化为灰烬飘散的效果(shadergraph|消融|粒子系统|特效)(代码片段)

...ShaderGraph环境准备三、模型准备:原神角色模型四、实现思路1、效果一的实现思路2、效果二的实现思路五、ShaderGraph具体实现1、效果一1.1、创建UnlitShaderGraph1.2、获取顶点坐标的y轴坐标1.3、滑块控制1.4、边缘噪声1.5、AlhpaClip... 查看详情

unity实现2d平面游戏角色跳跃(代码片段)

一.可能出现的问题1.怎么让角色跳起来2.如何判断角色是否跳跃3.如何判断角色是否可以跳跃二.解决方案1.可以通过给予一份力,使角色对象跳跃2.可以用碰撞检测来判断角色是否可以跳跃,是否已经跳跃。3.代码如下࿱... 查看详情

c语言实现扫雷游戏(一步步教你如何写扫雷)(代码片段)

扫雷游戏使用工具一、基本思路和流程1.扫雷游戏的游戏规则2.代码实现思路二、实现步骤(具体步骤)1.使用多文件形式2.代码实现定义各个难度等级的棋盘大小和雷的数量定义全局变量游戏规则界面菜单界面选择实现选... 查看详情

unity3d日常开发提高开发效率之定时器系统实现(代码片段)

...人博客QQ群:1040082875一、前言今天,来分享一下如何实现定时器。实现定时器需要搞明白二个问题:一、定时器如何实现二、为什么制作定时器系统首选,我们来了解一下如何在Unity里面实现定时器。二、Unity定时... 查看详情

unity3d日常开发提高开发效率之定时器系统实现(代码片段)

...人博客QQ群:1040082875一、前言今天,来分享一下如何实现定时器。实现定时器需要搞明白二个问题:一、定时器如何实现二、为什么制作定时器系统首选,我们来了解一下如何在Unity里面实现定时器。二、Unity定时... 查看详情

游戏开发实战教你在unity中实现笼中窥梦的效果(rendertexture|视觉差|多相机|渲染|shader|多场景)(代码片段)

...前天,有同学私信我,问我笼中窥梦的效果用Unity如何实现,如下是笼中窥梦的游戏画面不错,然后,我就用Unity实现了一下比较基础的效果,如下,下面我就来讲一下我的制作思路和过程吧~二、实现... 查看详情

面试官:redis如何实现每周热评功能?说说思路!(代码片段)

思路分析做每周热议,应该用缓存来做,如果直接查库的话,会对数据库造成压力。用缓存做的话,用Redis来做缓存的话比较合适一点。#利用Redsi添加数据命令#day:1指的是在1号的时候post:1第一篇文章添加了10条评... 查看详情

unity中实现雷达图(代码片段)

一:效果演示二:实现思路——描边思路:一开始觉得这很简单,就直接绘制一个比当前大一圈的雷达图就可以了,试了试发现并没有那么简单当每个顶点的权重都相同时,也就是雷达图为正多边形时绘制... 查看详情

unity中实现雷达图(代码片段)

一:效果演示二:实现思路——描边思路:一开始觉得这很简单,就直接绘制一个比当前大一圈的雷达图就可以了,试了试发现并没有那么简单当每个顶点的权重都相同时,也就是雷达图为正多边形时绘制... 查看详情

如何实现文件上传?说说你的思路(代码片段)

  一、是什么文件上传在日常开发中应用很广泛,我们发微博、发微信朋友圈都会用到了图片上传功能因为浏览器限制,浏览器不能直接操作文件系统,需要通过浏览器所暴露出来的统一接口,由用户主动授权发起来访问... 查看详情