using System; using System.Linq; using UnityEngine; namespace TFramework { [DisallowMultipleComponent] public class Outline : MonoBehaviour { public enum Mode { /// /// 描边所有轮廓 /// OutlineAll, /// /// 仅描边可见部分 /// OutlineVisible, /// /// 仅描边隐藏部分 /// OutlineHidden, /// /// 描边且剪影 /// OutlineAndSilhouette, /// /// 仅描边 /// SilhouetteOnly } /// /// 描边模式 /// public Mode OutlineMode { get { return outlineMode; } set { outlineMode = value; _isChange = true; } } /// /// 描边颜色 /// public Color OutlineColor { get { return outlineColor; } set { outlineColor = value; _isChange = true; } } /// /// 描边宽度 /// public float OutlineWidth { get { return outlineWidth; } set { outlineWidth = value; _isChange = true; } } [SerializeField] private Mode outlineMode; [SerializeField] private Color outlineColor; [SerializeField, Range(0f, 10f)] private float outlineWidth = 2f; private Renderer[] renderers; private Material outlineMaskMaterial; private Material outlineFillMaterial; private bool _isChange=false; void Awake() { renderers = GetComponentsInChildren(); // Instantiate outline materials outlineMaskMaterial = Instantiate(Main.GetMagr().m_outlineMaskMaterial); outlineFillMaterial = Instantiate(Main.GetMagr().m_outlineFillMaterial); outlineMaskMaterial.name = "OutlineMask (Instance)"; outlineFillMaterial.name = "OutlineFill (Instance)"; } void OnEnable() { foreach (var renderer in renderers) { var materials = renderer.sharedMaterials.ToList(); materials.Add(outlineMaskMaterial); materials.Add(outlineFillMaterial); renderer.materials = materials.ToArray(); } _isChange = true; } private void Update() { if(_isChange) { _isChange = false; UpdateMaterialProperties(); } } void OnDisable() { foreach (var renderer in renderers) { // Remove outline shaders var materials = renderer.sharedMaterials.ToList(); materials.Remove(outlineMaskMaterial); materials.Remove(outlineFillMaterial); renderer.materials = materials.ToArray(); } } void OnDestroy() { Destroy(outlineMaskMaterial); Destroy(outlineFillMaterial); } void UpdateMaterialProperties() { // Apply properties according to mode outlineFillMaterial.SetColor("_OutlineColor", outlineColor); switch (outlineMode) { case Mode.OutlineAll: outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always); outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always); outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth); break; case Mode.OutlineVisible: outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always); outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth); break; case Mode.OutlineHidden: outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always); outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater); outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth); break; case Mode.OutlineAndSilhouette: outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always); outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth); break; case Mode.SilhouetteOnly: outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater); outlineFillMaterial.SetFloat("_OutlineWidth", 0f); break; } } } }