using UnityEngine; using UnityEngine.Rendering; [RequireComponent(typeof(MeshFilter))] [RequireComponent(typeof(MeshRenderer))] public class GhostTrailGhost : MonoBehaviour { private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor"); private static readonly int ColorId = Shader.PropertyToID("_Color"); private MeshRenderer _meshRenderer; private GhostTrailEmitter _owner; private Material _runtimeMaterial; private Mesh _runtimeMesh; private bool _ownsRuntimeMesh; private float _lifeElapsed; private float _lifetime; private float _startAlpha; private float _endAlpha; private Color _baseColor; private bool _usesBaseColor; public void Initialize( Mesh mesh, Material templateMaterial, float lifetime, float startAlpha, float endAlpha, GhostTrailEmitter owner, bool ownsRuntimeMesh = false) { _owner = owner; _lifetime = Mathf.Max(0.01f, lifetime); _startAlpha = Mathf.Clamp01(startAlpha); _endAlpha = Mathf.Clamp01(endAlpha); _runtimeMesh = mesh; _ownsRuntimeMesh = ownsRuntimeMesh; MeshFilter meshFilter = GetComponent(); _meshRenderer = GetComponent(); meshFilter.sharedMesh = _runtimeMesh; _runtimeMaterial = new Material(templateMaterial); ConfigureTransparentMaterial(_runtimeMaterial); _usesBaseColor = _runtimeMaterial.HasProperty(BaseColorId); if (_usesBaseColor) { _baseColor = _runtimeMaterial.GetColor(BaseColorId); } else if (_runtimeMaterial.HasProperty(ColorId)) { _baseColor = _runtimeMaterial.GetColor(ColorId); } else { _baseColor = Color.white; } _meshRenderer.sharedMaterial = _runtimeMaterial; ApplyAlpha(_startAlpha); } private void Update() { _lifeElapsed += Time.deltaTime; float t = Mathf.Clamp01(_lifeElapsed / _lifetime); float alpha = Mathf.Lerp(_startAlpha, _endAlpha, t); ApplyAlpha(alpha); if (_lifeElapsed >= _lifetime) { Destroy(gameObject); } } private void OnDestroy() { if (_owner != null) { _owner.NotifyGhostDestroyed(this); } if (_runtimeMaterial != null) { Destroy(_runtimeMaterial); } if (_ownsRuntimeMesh && _runtimeMesh != null) { Destroy(_runtimeMesh); } } private void ApplyAlpha(float alpha) { Color color = _baseColor; color.a = alpha; if (_usesBaseColor) { _runtimeMaterial.SetColor(BaseColorId, color); return; } if (_runtimeMaterial.HasProperty(ColorId)) { _runtimeMaterial.SetColor(ColorId, color); } } private static void ConfigureTransparentMaterial(Material material) { if (material.HasProperty("_Surface")) material.SetFloat("_Surface", 1f); if (material.HasProperty("_Blend")) material.SetFloat("_Blend", 0f); if (material.HasProperty("_AlphaClip")) material.SetFloat("_AlphaClip", 0f); if (material.HasProperty("_SrcBlend")) material.SetFloat("_SrcBlend", (float)BlendMode.SrcAlpha); if (material.HasProperty("_DstBlend")) material.SetFloat("_DstBlend", (float)BlendMode.OneMinusSrcAlpha); if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0f); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = (int)RenderQueue.Transparent; } }