需求:相机和人物之间有遮挡物,将遮挡物做半透明处理,shader如下
Shader "Custom/Diffuse/Transparent" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {
}
_TransparentScale("Transparent",Range(0,1)) = 1
}
SubShader {
Tags {
"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
LOD 200
CGPROGRAM
#pragma surface surf Lambert noforwardadd alpha:fade
sampler2D _MainTex;
float _TransparentScale;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a * _TransparentScale;
}
ENDCG
}
Fallback "Mobile/VertexLit"
}
用的cinemachine实现相机跟随,需要美术同学把实现半透效果的模型添加colider组件,用于射线查询
逻辑为 tag为obstacle的物体实现半透,tag为totally_transparent的物体实现全透
using System.Collections.Generic;
using UnityEngine;
public class test: MonoBehaviour
{
List<GameObject> mTransparentGameobject = new List<GameObject>();
List<GameObject> mTransparentGameobject2 = new List<GameObject>();
void Update()
{
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
//这里用的是tag,建议采用layer
RaycastHit[] hits = Physics.RaycastAll(ray, 100);
mTransparentGameobject2.Clear();
foreach (var hit in hits)
{
Debug.DrawLine(ray.origin, hit.point, Color.red);
if (hit.collider.tag != "obstacle" && hit.collider.tag != "totally_transparent")
{
continue;
}
GameObject go = hit.transform.gameObject;
mTransparentGameobject2.Add(go);
SetGameObjectTransparent(go, true);
if (mTransparentGameobject.Contains(go))
{
mTransparentGameobject.Remove(go);
}
}
SetGameObjectTransparent(mTransparentGameobject, false);
List<GameObject> temp = mTransparentGameobject;
mTransparentGameobject = mTransparentGameobject2;
mTransparentGameobject2 = temp;
}
void SetGameObjectTransparent(List<GameObject> list, bool t)
{
foreach (var go in list)
{
SetGameObjectTransparent(go, false);
}
}
void SetGameObjectTransparent(GameObject obj, bool transparent)
{
if (obj == null) return;
if (obj.tag == "totally_transparent")
{
SetGameObjectTotallyTransparent(obj, transparent);
return;
}
SetGOTransparent(obj, transparent);
}
string transparentName = "Custom/Diffuse/Transparent";
string defaultName = "Mobile/Diffuse";
void SetGOTransparent(GameObject obj, bool transparent)
{
string name = transparent ? transparentName : defaultName;
Shader shader = Shader.Find(name);
//float a = transparent ? 0.2f : 1f;
MeshRenderer[] meshs = obj.transform.GetComponentsInChildren<MeshRenderer>();
foreach (var item in meshs)
{
//item.enabled = !transparent;
Material[] m = item.transform.GetComponent<MeshRenderer>().materials;
for (int i = 0; i < m.Length; ++i)
{
SetTransparent(m[i], shader, transparent);
}
};
}
void SetTransparent(Material m, Shader s, bool transparent)
{
m.shader = s;
if (transparent)
{
m.SetFloat("_TransparentScale", 0.2f);
}
}
void SetGameObjectTotallyTransparent(GameObject obj, bool transparent)
{
MeshRenderer[] meshs = obj.transform.GetComponentsInChildren<MeshRenderer>();
foreach (var item in meshs)
{
item.enabled = !transparent;
};
}
private void OnDisable()
{
SetGameObjectTransparent(mTransparentGameobject, false);
mTransparentGameobject.Clear();
}
}