[Unity Shaders] 地图和人物的遮挡关系处理
第一种方法:
射线检测的方法
思路:做一条主相机和人物之间的射线,如果地图上的墙遮挡了人物模型,这条射线一定和
墙相交。检测到相交之后将墙壁的材质设为透明材质。实现遮挡人物的显示。
废话不多说上图:
在做射线的时候,射线是很容易和人物相交的,所以要加一个判断的tags、
下面放出代码
/**
射线检测出在相机和玩家之间的碰撞体,设置透明Material
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayTest : MonoBehaviour {
public Camera playerCamera;
public Material blendMat;
public Material commonMat;
private Transform playerPos
{
get
{
return gameObject.GetComponent<Transform>();
}
}
private GameObject blendWall;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
var direction = playerPos.position - playerCamera.transform.position;
RaycastHit hit;
if (Physics.Raycast(playerCamera.transform.position, Vector3.Normalize(direction), out hit ,Vector3.Magnitude(direction)))
{
if (hit.collider.tag == "Wall")
{
Debug.DrawLine(playerCamera.transform.position, hit.point, Color.red);
blendWall = hit.collider.gameObject;
blendWall.GetComponent<Renderer>().material = blendMat;
return;
}
}
if(blendWall != null)
blendWall.GetComponent<Renderer>().material = commonMat;
}
}
结果截图
* 第二种方法*
使用Ztest绘制的方法
思路:
修改人物的渲染顺序,将人物的渲染放在墙体的后面。
Tags {"Queue" = "Transparent+5"}
没有遮挡的部分 ZWrite On ZTest LEqual
遮挡的部分 ZTest Greater Lighting Off ZWrite Off
如果墙体是透明的,必须要确保墙体的深度缓存是写入过的。
Pass
{
ZWrite On
ColorMask 0
}
另外做一个Pass写入深度缓存
放出部分代码:
Pass
{
Offset -50,0
ZTest Greater
Lighting Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vertBlend
#pragma fragment fragBlend
ENDCG
}
Pass
{
ZWrite On
ZTest LEqual
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
我的第二种方法主要参考的是这篇文章