基于视野(FOV)的战争迷雾,例如LOL的视野:鼠标右键点击地板,目标移动,同时显示角色周围视野,鼠标滚轮可以调节远近。

Unity版本:2019.4.1f1

1.新建工程---右键3D Object---Terrain,随便刷一个地形,尽量高低错落,设置地形大小为100*100

2.导入文件,在Camera上添加Fog Of War Effect脚本,脚本会自动添加<Flare Layer>组件,Unity 2018之前的版本需要添加<GUI Layer>组件,2019以后版本被舍弃,无需添加

 3.右键创建一个胶囊,模拟玩家,添加NavMeshAgent组件,添加Fog Of War Explorer脚本

using UnityEngine;
using UnityEngine.AI;/// <summary>
/// 视野数据-由于计算fov是在子线程操作,通过将视野数据以object类型参数传入,
/// 使用简单数据类型或结构体会产生装箱操作,因此将视野封装成类
/// </summary>
public class FOWFieldData
{public float radiusSquare;public Vector3 position;public float radius;public FOWFieldData(Vector3 position, float radius){this.position = position;this.radius = radius;this.radiusSquare = radius * radius;}
}/// <summary>
/// Player
/// </summary>
public class FogOfWarExplorer : MonoBehaviour
{[Range(10, 25)] public float radius = 15;//视野半径private Vector3 m_OriginPosition;private FOWMapPos m_FowMapPos;private FOWFieldData m_FieldData;private bool m_IsInitialized;private float distance = 24;//摄像机高度private float angle = 45;//摄像机偏移角度private Vector3 m_CameraPosition;private NavMeshAgent m_Agent;void Start(){m_FieldData = new FOWFieldData(transform.position, radius);m_Agent = gameObject.GetComponent<NavMeshAgent>();Camera.main.transform.rotation = Quaternion.Euler(angle, 0, 0);Camera.main.transform.position = transform.position - Camera.main.transform.forward * distance;}void Update(){if (radius <= 0)return;if (m_OriginPosition != transform.position){m_OriginPosition = transform.position;var pos = FogOfWarEffect.WorldPositionToFOW(transform.position);if (m_FowMapPos.x != pos.x || m_FowMapPos.y != pos.y || !m_IsInitialized){m_FowMapPos = pos;m_IsInitialized = true;m_FieldData.position = transform.position;m_FieldData.radius = radius;//FogOfWarEffect.SetVisibleAtPosition(m_FieldData);FogOfWarEffect.UpdateFOWFieldData(m_FieldData);}}m_CameraPosition = transform.position - Camera.main.transform.forward * distance;Camera.main.transform.position = Vector3.Lerp(Camera.main.transform.position, m_CameraPosition, Time.deltaTime * 3f);BasicOperation();}void OnDestroy(){if (m_FieldData != null)FogOfWarEffect.ReleaseFOWFieldData(m_FieldData);m_FieldData = null;}void OnDrawGizmosSelected(){Gizmos.color = Color.blue;Gizmos.DrawWireSphere(transform.position, radius);}void BasicOperation() {if (Input.GetMouseButtonDown(1))//鼠标右键点击地板{Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if (Physics.Raycast(ray, out hit)){m_Agent.SetDestination(hit.point);}}if (Input.GetAxis("Mouse ScrollWheel") > 0){if (distance >= 7)distance -= 2;}if (Input.GetAxis("Mouse ScrollWheel") < 0){if (distance <= 35)distance += 2;}}}

 4.Scene视角切换成俯视视角,方便调整参数。调整战争迷雾蒙版类型、宽度、高度、战争迷雾中心位置,将特效shader、模糊shader、小地图shader拖入Main Camera上的Fog Of War Effect上

using ASL.FogOfWar;
using System.Collections.Generic;
using UnityEngine;public struct FOWMapPos
{public int x;public int y;public FOWMapPos(int x, int y){this.x = x;this.y = y;}
}/// <summary>
/// 屏幕空间战争迷雾
/// </summary>
[RequireComponent(typeof(FlareLayer))]
public class FogOfWarEffect : MonoBehaviour
{//迷雾蒙版类型public enum FogMaskType{/// <summary>/// 精确计算的FOV/// </summary>AccurateFOV,/// <summary>/// 基础FOV/// </summary>BasicFOV,/// <summary>/// 简单圆形/// </summary>Circular,}//实例化public static FogOfWarEffect Instance{get{if (instance == null)instance = FindObjectOfType<FogOfWarEffect>();return instance;}}private static FogOfWarEffect instance;/// <summary>/// 迷雾蒙版类型/// </summary>public FogMaskType fogMaskType { get { return m_FogMaskType; } }/// <summary>/// 战争迷雾颜色(RGB迷雾颜色,Alpha已探索区域透明度)/// </summary>public Color fogColor { get { return m_FogColor; } }/// <summary>/// 迷雾区域宽度/// </summary>public float xSize { get { return m_XSize; } }/// <summary>/// 迷雾区域高度/// </summary>public float zSize { get { return m_ZSize; } }/// <summary>/// 迷雾贴图宽度/// </summary>public int texWidth { get { return m_TexWidth; } }/// <summary>/// 迷雾贴图高度/// </summary>public int texHeight { get { return m_TexHeight; } }/// <summary>/// 迷雾区域中心坐标/// </summary>public Vector3 centerPosition { get { return m_CenterPosition; } }public float heightRange { get { return m_HeightRange; } }public Texture2D fowMaskTexture{get{if (m_Map != null)return m_Map.GetFOWTexture();return null;}}public RenderTexture minimapMask{get{if (!m_GenerateMinimapMask)return null;return m_Renderer.GetMimiMapMask();}}[Header("战争迷雾蒙版类型")][SerializeField]private FogMaskType m_FogMaskType;[Header("战争迷雾颜色")][SerializeField]private Color m_FogColor = Color.black;[Header("战争迷雾宽度")][SerializeField]private float m_XSize = 77f;[Header("战争迷雾高度")][SerializeField]private float m_ZSize = 77f;[Header("战争迷雾贴图宽度")][SerializeField]private int m_TexWidth = 66;[Header("战争迷雾贴图高度")][SerializeField]private int m_TexHeight = 66;[Header("战争迷雾中心位置")][SerializeField]private Vector3 m_CenterPosition;[Header("高度随机值")][SerializeField]private float m_HeightRange = 1.23f;/// <summary>/// 模糊偏移量/// /// </summary>[Header("模糊偏移量")][SerializeField]private float m_BlurOffset = 0.003f;/// <summary>/// 模糊迭代次数/// </summary>[Header("模糊迭代次数")][SerializeField]private int m_BlurInteration = 2;/// <summary>/// 是否生成小地图蒙版/// </summary>private bool m_GenerateMinimapMask;/// <summary>/// 迷雾特效shader/// </summary>[Header("战争特效Shader")] public Shader effectShader;/// <summary>/// 模糊shader/// </summary>[Header("模糊Shader")] public Shader blurShader;/// <summary>/// 小地图蒙版渲染shader/// </summary>[Header("小地图蒙版渲染Shader")] public Shader minimapRenderShader;[Header("更新周期")][Range(0.0f,1.0f)]public float UpdateTime = 1.0f;/// <summary>/// 预生成的地图FOV数据(如果为空则使用实时计算FOV)/// </summary>//public FOWPregenerationFOVMapData pregenerationFOVMapData;/// <summary>/// 战争迷雾地图对象/// </summary>private FOWMap m_Map;/// <summary>/// 战争迷雾渲染器/// </summary>private FOWRenderer m_Renderer;private bool m_IsInitialized;private float m_MixTime = 0.0f;private float m_RefreshTime = 0.0f;private float m_DeltaX;private float m_DeltaZ;private float m_InvDeltaX;private float m_InvDeltaZ;private Camera m_Camera;private const float kDispearSpeed = 3f;private const float kRefreshTextureSpeed = 4.0f;private Vector3 m_BeginPos;private List<FOWFieldData> m_FieldDatas;private bool m_IsFieldDatasUpdated;void Awake(){m_IsInitialized = Init();}void OnDestroy(){if (m_Renderer != null)m_Renderer.Release();if (m_Map != null)m_Map.Release();if (m_FieldDatas != null)m_FieldDatas.Clear();m_FieldDatas = null;m_Renderer = null;m_Map = null;instance = null;}void FixedUpdate(){/*更新迷雾纹理*/if (m_MixTime >= UpdateTime){if (m_RefreshTime >= UpdateTime){m_RefreshTime = 0.0f;if (m_Map.RefreshFOWTexture()){m_Renderer.SetFogFade(0);m_MixTime = 0;m_IsFieldDatasUpdated = false;//m_Renderer.SetFogTexture(m_Map.GetFOWTexture());}}else{m_RefreshTime += Time.deltaTime * kRefreshTextureSpeed;}}else{m_MixTime += Time.deltaTime * kDispearSpeed;m_Renderer.SetFogFade(m_MixTime);}}private bool Init(){if (m_XSize <= 0 || m_ZSize <= 0 || m_TexWidth <= 0 || m_TexHeight <= 0)return false;if (effectShader == null || !effectShader.isSupported)return false;m_Camera = gameObject.GetComponent<Camera>();if (m_Camera == null)return false;m_Camera.depthTextureMode |= DepthTextureMode.Depth;m_DeltaX = m_XSize / m_TexWidth;m_DeltaZ = m_ZSize / m_TexHeight;m_InvDeltaX = 1.0f / m_DeltaX;m_InvDeltaZ = 1.0f / m_DeltaZ;m_BeginPos = m_CenterPosition - new Vector3(m_XSize * 0.5f, 0, m_ZSize * 0.5f);m_Renderer = new FOWRenderer(effectShader, blurShader, minimapRenderShader, m_CenterPosition, m_XSize, m_ZSize, m_FogColor, m_BlurOffset, m_BlurInteration);m_Map = new FOWMap(m_FogMaskType, m_BeginPos, m_XSize, m_ZSize, m_TexWidth, m_TexHeight, m_HeightRange);IFOWMapData md = gameObject.GetComponent<IFOWMapData>();if (md != null)m_Map.SetMapData(md);else{m_Map.SetMapData(new FOWMapData(m_TexHeight, m_TexHeight));m_Map.GenerateMapData(m_HeightRange);}if (minimapRenderShader != null)m_GenerateMinimapMask = true;return true;}/// <summary>/// 世界坐标转战争迷雾坐标/// </summary>/// <param name="position"></param>/// <returns></returns>public static FOWMapPos WorldPositionToFOW(Vector3 position){if (!Instance)return default(FOWMapPos);if (!Instance.m_IsInitialized)return default(FOWMapPos);int x = Mathf.FloorToInt((position.x - Instance.m_BeginPos.x) * Instance.m_InvDeltaX);int z = Mathf.FloorToInt((position.z - Instance.m_BeginPos.z) * Instance.m_InvDeltaZ);return new FOWMapPos(x, z);}public static Vector2 WorldPositionTo2DLocal(Vector3 position){if (!Instance)return default(Vector2);if (!Instance.m_IsInitialized)return default(Vector2);Vector2 pos = default(Vector2);pos.x = (position.x - Instance.m_BeginPos.x) / Instance.m_XSize;pos.y = (position.z - Instance.m_BeginPos.z) / Instance.m_ZSize;return pos;}/ <summary>/ 将指定位置设置为可见/ </summary>/ <param name="fieldData">视野</param>//public static void SetVisibleAtPosition(FOWFieldData fieldData)//{//    if (!Instance)//        return;//    if (!Instance.m_IsInitialized)//        return;//    if (fieldData == null)//        return;//    Instance.m_Map.SetVisible(fieldData);//}public static void UpdateFOWFieldData(FOWFieldData data){if (!Instance)return;if (!Instance.m_IsInitialized)return;if (Instance.m_FieldDatas == null)Instance.m_FieldDatas = new List<FOWFieldData>();if (!Instance.m_FieldDatas.Contains(data)){Instance.m_FieldDatas.Add(data);}if (!Instance.m_IsFieldDatasUpdated){//lock (Instance.m_FieldDatas){Instance.m_Map.SetVisible(Instance.m_FieldDatas);Instance.m_IsFieldDatasUpdated = true;}}}public static void ReleaseFOWFieldData(FOWFieldData data){if (!instance)return;if (!instance.m_IsInitialized)return;//lock (instance.m_FieldDatas){if (instance.m_FieldDatas != null && instance.m_FieldDatas.Contains(data))instance.m_FieldDatas.Remove(data);}}/// <summary>/// 是否在地图中可见/// </summary>/// <param name="position"></param>/// <returns></returns>public static bool IsVisibleInMap(Vector3 position){if (!Instance)return true;if (!Instance.m_IsInitialized)return true;int x = Mathf.FloorToInt((position.x - Instance.m_BeginPos.x) * Instance.m_InvDeltaX);int z = Mathf.FloorToInt((position.z - Instance.m_BeginPos.z) * Instance.m_InvDeltaZ);return Instance.m_Map.IsVisibleInMap(x, z);}void OnRenderImage(RenderTexture src, RenderTexture dst){if (!m_IsInitialized)Graphics.Blit(src, dst);else{m_Renderer.RenderFogOfWar(m_Camera, m_Map.GetFOWTexture(), src, dst);}}void OnDrawGizmosSelected(){FOWUtils.DrawFogOfWarGizmos(m_CenterPosition, m_XSize, m_ZSize, m_TexWidth, m_TexHeight, m_HeightRange);}
}

 5.单击Terrain 右上角勾选静态Static,Windows----AI---Navigation,Bake---Bake

6.运行即可查看效果,你还可以添加小地图和右键点击动画等效果。

如果你的场景和我的不一样,那也没关系,我改了光照设置,不改也没问题,我的光照设置如下:

资源下载:点击下载

网盘下载:访问码:2oeb

参考资料:GitHub

Unity MOBA类型游戏的战争迷雾效果相关推荐

  1. 在Unity中为即时战略游戏实现战争迷雾(上)

    本文将由游戏开发工程师Ariel Coppes分享在Unity中为即时战略游戏实现战争迷雾效果. 过去三年中,我一直在Ironhide Game Studio开发移动即时战略游戏<钢铁战队> ...

  2. 在Unity中为即时战略游戏实现战争迷雾(下)

    本文将在Unity中为即时战略游戏实现战争迷雾的一种新方法. 在上一篇文章中,游戏开发工程师Ariel Coppes分享了<钢铁战队>中战争迷雾效果的实现方法,本文他将介绍新的一种实现方法 ...

  3. 2D游戏的战争迷雾实现方式

    转自: http://bbs.gameres.com/forum.php?mod=viewthread&tid=201878&extra=page%3D16%26filter%3Dso ...

  4. 【笨木头Cocos2dx 041】战争迷雾效果 第4章_真正的迷雾来了!

    错过了前面章节? 没关系,传送门在这: 战争迷雾效果 第1章_要探索,不要地图全开! 战争迷雾效果 第2章_先把地图加进来 战争迷雾效果 第3章_准确地获取屏幕上的瓦片位置 经过这么多铺垫,我们要来正 ...

  5. 战争迷雾效果 第4章_真正的迷雾来了!

    原文地址:http://www.benmutou.com/blog/archives/485 经过这么多铺垫,我们要来正式编写实现迷雾效果的代码了. (小若:快点开始写,别唠叨了!) 笨木头花心贡献, ...

  6. 战争迷雾效果 第05章 项目源码下载

    笨木头花心贡献,啥?花心?不呢,是用心~ 转载请注明,原文地址:http://www.benmutou.com/blog/archives/502 正文: 关于战争迷雾效果的项目源码一直没有放出来,原 ...

  7. Unity3D技术开发之战争迷雾效果

    相信玩过Dota,英雄联盟等即时竞技类游戏的朋友都知道战争迷雾,这次做了一个战争迷雾的效果: 战争迷雾大家应该很熟悉了,一开始地图全部都是黑的,只有主角的一定范围内能看得到.随着主角的移动,未探索的区 ...

  8. cocos2dx 实现战争迷雾效果

    游戏里面的战争迷雾或者刮刮乐效果可以用下面的方法实现 function MainScene:onCreate()local strVertSource = "attribute vec4 a ...

  9. Unity3D战争迷雾效果

    战争迷雾demo视频 这次做了一个战争迷雾的效果: 战争迷雾大家应该很熟悉了,一开始地图全部都是黑的,只有主角的一定范围内能看得到.随着主角的移动,未探索的区域变成了可见. 我这个demo还做了视角切 ...

最新文章

  1. tomcat结合nginx使用小结
  2. 百度语音识别技术负责人李先刚:如何利用Deep CNN大幅提升识别准确率?
  3. kafka的消费隔离级别(持续更新中)
  4. 请教设计模式大牛们几点
  5. 诗和远方:无题(四十六)
  6. 03-树3 Tree Traversals Again
  7. String.format()方法使用
  8. mysql tuner sh_MySQL性能提议者:mysqltuner.pl
  9. adb:设置手机屏幕亮度
  10. 查重有风险,小心论文被买卖!——iThenticate官方论文查重系统登录中国!
  11. linux centos fedora 安装LBP2900打印机 LBP6230dn LBP6240dn
  12. Weakly Supervised Instance Segmentation using Class Peak Response
  13. 棋牌---这些年使用过的技术
  14. 一步一步用debugserver + lldb代替gdb进行动态调试(整理与补充)
  15. Memcache/Redis集群管理探索与实现:美图开源PaaS平台资源网关
  16. 小众爱好之滑翔伞运动
  17. 计算机动画专业要学什么课程,学动画专业的应该用什么什么配置的笔记本电脑?...
  18. python初中级开发面经(持续更新2020-3-7)
  19. Unity局域网传输图片等文件
  20. Cluster Linking

热门文章

  1. iphone资料 各种网址搜集
  2. Windows系统打开Linux下Ext格式磁盘方式
  3. 狂神说 SpringCloud 笔记
  4. GMIC秒拍移动视频峰会|行业大咖齐聚,畅谈短视频平台力量
  5. jenkins 使用教程
  6. PTA 7-170 公约数与公倍数
  7. 【引用】USB 2.0 A型、B型、Mini和Micro接口定义及封装 - 天缘博客
  8. 苹果x面容id不可用是什么原因_苹果全系列面容都可以修复了无面容iPhone有救了?...
  9. 2018中国电子制造设备自动化市场研究
  10. 太牛了!用文言文来编程,97年CMU本科生火遍全网!