战争迷雾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)
更多推荐
所有评论(0)