using UnityEngine;
///
/// 材质渲染模式助手类
/// 用于设置材质的正确渲染模式以支持透明度
///
public static class MaterialRenderModeHelper
{
public enum BlendMode
{
Opaque,
Cutout,
Fade, // Traditional transparency (ZWrite OFF)
Transparent, // Physically based transparency (ZWrite OFF)
AlphaBlendWithDepth // Alpha blend with depth write (ZWrite ON) - 解决Body显示问题
}
///
/// 设置材质的渲染模式
///
/// 要设置的材质
/// 渲染模式
public static void SetMaterialRenderMode(Material material, BlendMode blendMode)
{
switch (blendMode)
{
case BlendMode.Opaque:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
case BlendMode.Cutout:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
break;
case BlendMode.Fade:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
break;
case BlendMode.Transparent:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
break;
case BlendMode.AlphaBlendWithDepth:
// 关键修复:保持深度写入的透明混合模式
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 1); // 保持深度写入,这样Body即使单独存在也能正确显示
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
// 使用较早的渲染队列,确保在其他透明物体之前渲染
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry + 450;
break;
}
}
///
/// 自动检测并设置合适的渲染模式
///
/// 材质
/// 透明度值
public static void AutoSetRenderMode(Material material, float alpha)
{
if (alpha >= 1.0f)
{
SetMaterialRenderMode(material, BlendMode.Opaque);
}
else
{
SetMaterialRenderMode(material, BlendMode.AlphaBlendWithDepth);
}
}
///
/// 专门为Body设置渲染模式
/// 确保Body在单独显示时也能正确显示
///
/// Body材质
/// 透明度值
public static void SetBodyRenderMode(Material material, float alpha)
{
if (alpha >= 1.0f)
{
SetMaterialRenderMode(material, BlendMode.Opaque);
}
else
{
// 对于Body,始终使用保持深度写入的透明模式
SetMaterialRenderMode(material, BlendMode.AlphaBlendWithDepth);
}
}
}