248 lines
6.8 KiB
C#
248 lines
6.8 KiB
C#
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
|
|
}
|