2026.06.24
This commit is contained in:
247
Assets/My project/maze Scripts/Ui/FootprintEffect.cs
Normal file
247
Assets/My project/maze Scripts/Ui/FootprintEffect.cs
Normal file
@@ -0,0 +1,247 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public class FootprintEffect : MonoBehaviour
|
||||
{
|
||||
[Header("Timing")]
|
||||
[SerializeField] private float appearTime = 0.25f;
|
||||
[SerializeField] private float lifeTime = 3f;
|
||||
[SerializeField] private float fadeTime = 0.8f;
|
||||
|
||||
[Header("Scale Effect")]
|
||||
[SerializeField] private bool useScaleEffect = true;
|
||||
[SerializeField] private float startScaleMultiplier = 0.75f;
|
||||
[SerializeField] private float popScaleMultiplier = 1.08f;
|
||||
[SerializeField] private float endScaleMultiplier = 0.85f;
|
||||
|
||||
[Header("Unlit Brightness Effect")]
|
||||
[Tooltip("URP Unlit 머티리얼에서 Emission 대신 색 밝기를 조절합니다.")]
|
||||
[SerializeField] private bool useBrightnessEffect = true;
|
||||
[SerializeField] private float appearBrightness = 1.4f;
|
||||
[SerializeField] private float normalBrightness = 1.0f;
|
||||
[SerializeField] private float fadeBrightness = 0.5f;
|
||||
|
||||
[Header("Destroy")]
|
||||
[SerializeField] private bool destroyAfterFade = true;
|
||||
[Tooltip("renderer.materials로 생성된 머티리얼 인스턴스를 OnDestroy에서 정리합니다.")]
|
||||
[SerializeField] private bool cleanupMaterialInstances = true;
|
||||
|
||||
private Renderer[] renderers;
|
||||
private Material[] materials;
|
||||
private Color[] originalColors;
|
||||
private Vector3 originalScale;
|
||||
private Coroutine effectRoutine;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
originalScale = transform.localScale;
|
||||
CacheMaterials();
|
||||
ApplyVisual(0f, startScaleMultiplier, fadeBrightness);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (effectRoutine != null)
|
||||
StopCoroutine(effectRoutine);
|
||||
|
||||
effectRoutine = StartCoroutine(EffectRoutine());
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (effectRoutine != null)
|
||||
{
|
||||
StopCoroutine(effectRoutine);
|
||||
effectRoutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (!cleanupMaterialInstances || materials == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < materials.Length; i++)
|
||||
{
|
||||
if (materials[i] != null)
|
||||
Destroy(materials[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CacheMaterials()
|
||||
{
|
||||
renderers = GetComponentsInChildren<Renderer>(true);
|
||||
|
||||
int materialCount = 0;
|
||||
|
||||
for (int i = 0; i < renderers.Length; i++)
|
||||
materialCount += renderers[i].materials.Length;
|
||||
|
||||
materials = new Material[materialCount];
|
||||
originalColors = new Color[materialCount];
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < renderers.Length; i++)
|
||||
{
|
||||
Material[] rendererMaterials = renderers[i].materials;
|
||||
|
||||
for (int j = 0; j < rendererMaterials.Length; j++)
|
||||
{
|
||||
materials[index] = rendererMaterials[j];
|
||||
originalColors[index] = GetMaterialColor(materials[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator EffectRoutine()
|
||||
{
|
||||
yield return AppearRoutine();
|
||||
|
||||
if (lifeTime > 0f)
|
||||
yield return new WaitForSeconds(lifeTime);
|
||||
|
||||
yield return FadeRoutine();
|
||||
|
||||
effectRoutine = null;
|
||||
|
||||
if (destroyAfterFade)
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
private IEnumerator AppearRoutine()
|
||||
{
|
||||
if (appearTime <= 0f)
|
||||
{
|
||||
ApplyVisual(1f, 1f, normalBrightness);
|
||||
yield break;
|
||||
}
|
||||
|
||||
float timer = 0f;
|
||||
|
||||
while (timer < appearTime)
|
||||
{
|
||||
timer += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(timer / appearTime);
|
||||
|
||||
float alpha = Mathf.Lerp(0f, 1f, t);
|
||||
float brightness = useBrightnessEffect
|
||||
? Mathf.Lerp(fadeBrightness, appearBrightness, t)
|
||||
: 1f;
|
||||
|
||||
float scaleMultiplier;
|
||||
|
||||
if (t < 0.75f)
|
||||
{
|
||||
float popT = t / 0.75f;
|
||||
scaleMultiplier = Mathf.Lerp(startScaleMultiplier, popScaleMultiplier, popT);
|
||||
}
|
||||
else
|
||||
{
|
||||
float settleT = (t - 0.75f) / 0.25f;
|
||||
scaleMultiplier = Mathf.Lerp(popScaleMultiplier, 1f, settleT);
|
||||
}
|
||||
|
||||
ApplyVisual(alpha, scaleMultiplier, brightness);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
ApplyVisual(1f, 1f, normalBrightness);
|
||||
}
|
||||
|
||||
private IEnumerator FadeRoutine()
|
||||
{
|
||||
if (fadeTime <= 0f)
|
||||
{
|
||||
ApplyVisual(0f, endScaleMultiplier, fadeBrightness);
|
||||
yield break;
|
||||
}
|
||||
|
||||
float timer = 0f;
|
||||
|
||||
while (timer < fadeTime)
|
||||
{
|
||||
timer += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(timer / fadeTime);
|
||||
|
||||
float alpha = Mathf.Lerp(1f, 0f, t);
|
||||
float brightness = useBrightnessEffect
|
||||
? Mathf.Lerp(normalBrightness, fadeBrightness, t)
|
||||
: 1f;
|
||||
|
||||
float scaleMultiplier = Mathf.Lerp(1f, endScaleMultiplier, t);
|
||||
|
||||
ApplyVisual(alpha, scaleMultiplier, brightness);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
ApplyVisual(0f, endScaleMultiplier, fadeBrightness);
|
||||
}
|
||||
|
||||
private void ApplyVisual(float alpha, float scaleMultiplier, float brightness)
|
||||
{
|
||||
if (useScaleEffect)
|
||||
transform.localScale = originalScale * scaleMultiplier;
|
||||
|
||||
if (materials == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < materials.Length; i++)
|
||||
{
|
||||
if (materials[i] == null)
|
||||
continue;
|
||||
|
||||
Color color = originalColors[i];
|
||||
color.r *= brightness;
|
||||
color.g *= brightness;
|
||||
color.b *= brightness;
|
||||
color.a = alpha;
|
||||
|
||||
SetMaterialColor(materials[i], color);
|
||||
}
|
||||
}
|
||||
|
||||
private Color GetMaterialColor(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
return Color.white;
|
||||
|
||||
if (material.HasProperty("_BaseColor"))
|
||||
return material.GetColor("_BaseColor");
|
||||
|
||||
if (material.HasProperty("_Color"))
|
||||
return material.GetColor("_Color");
|
||||
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
private void SetMaterialColor(Material material, Color color)
|
||||
{
|
||||
if (material == null)
|
||||
return;
|
||||
|
||||
if (material.HasProperty("_BaseColor"))
|
||||
material.SetColor("_BaseColor", color);
|
||||
else if (material.HasProperty("_Color"))
|
||||
material.SetColor("_Color", color);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
appearTime = Mathf.Max(0f, appearTime);
|
||||
lifeTime = Mathf.Max(0f, lifeTime);
|
||||
fadeTime = Mathf.Max(0f, fadeTime);
|
||||
|
||||
startScaleMultiplier = Mathf.Max(0.01f, startScaleMultiplier);
|
||||
popScaleMultiplier = Mathf.Max(0.01f, popScaleMultiplier);
|
||||
endScaleMultiplier = Mathf.Max(0.01f, endScaleMultiplier);
|
||||
|
||||
appearBrightness = Mathf.Max(0f, appearBrightness);
|
||||
normalBrightness = Mathf.Max(0f, normalBrightness);
|
||||
fadeBrightness = Mathf.Max(0f, fadeBrightness);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user