- ToonPostProcess.shader: 횃불 고딕 스타일 후처리 쉐이더 (Built-in RP) - ToonCameraEffect.cs: 카메라 자동 부착 후처리 스크립트 - 중복 UI 스크립트 제거 (MenuIntroController, ToggleCustom) - 씬, 프리팹, 애니메이션 등 전체 업데이트 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
123 lines
3.8 KiB
C#
123 lines
3.8 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
public class MenuIntroController : MonoBehaviour
|
|
{
|
|
[System.Serializable]
|
|
public class MenuItem
|
|
{
|
|
public RectTransform rect;
|
|
public CanvasGroup canvasGroup;
|
|
public float delay;
|
|
[HideInInspector] public Vector2 targetPosition;
|
|
}
|
|
|
|
public MenuItem[] menuItems;
|
|
|
|
public float moveDistance = 80f;
|
|
public float introDuration = 0.6f; // 나타날 때 속도
|
|
public float outroDuration = 0.3f; // 사라질 때 속도
|
|
public AnimationCurve ease = AnimationCurve.EaseInOut(0, 0, 1, 1);
|
|
|
|
private void Awake()
|
|
{
|
|
foreach (MenuItem item in menuItems)
|
|
{
|
|
item.targetPosition = item.rect.anchoredPosition;
|
|
item.rect.anchoredPosition = item.targetPosition + new Vector2(moveDistance, 0f);
|
|
item.canvasGroup.alpha = 0f;
|
|
item.canvasGroup.interactable = false;
|
|
item.canvasGroup.blocksRaycasts = false;
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
StartCoroutine(PlayIntro());
|
|
}
|
|
|
|
// ── 인트로 (슬라이드 인) ───────────────────
|
|
private IEnumerator PlayIntro()
|
|
{
|
|
foreach (MenuItem item in menuItems)
|
|
StartCoroutine(AnimateItemIn(item));
|
|
|
|
yield return null;
|
|
}
|
|
|
|
private IEnumerator AnimateItemIn(MenuItem item)
|
|
{
|
|
yield return new WaitForSeconds(item.delay);
|
|
|
|
float time = 0f;
|
|
Vector2 startPos = item.targetPosition + new Vector2(moveDistance, 0f);
|
|
|
|
while (time < introDuration)
|
|
{
|
|
time += Time.deltaTime;
|
|
float curved = ease.Evaluate(Mathf.Clamp01(time / introDuration));
|
|
|
|
item.rect.anchoredPosition = Vector2.Lerp(startPos, item.targetPosition, curved);
|
|
item.canvasGroup.alpha = Mathf.Lerp(0f, 1f, curved);
|
|
yield return null;
|
|
}
|
|
|
|
item.rect.anchoredPosition = item.targetPosition;
|
|
item.canvasGroup.alpha = 1f;
|
|
item.canvasGroup.interactable = true;
|
|
item.canvasGroup.blocksRaycasts = true;
|
|
}
|
|
|
|
// ── 아웃트로 (슬라이드 아웃) ───────────────
|
|
public IEnumerator PlayOutro()
|
|
{
|
|
foreach (MenuItem item in menuItems)
|
|
StartCoroutine(AnimateItemOut(item));
|
|
|
|
float maxWait = 0f;
|
|
foreach (MenuItem item in menuItems)
|
|
maxWait = Mathf.Max(maxWait, item.delay);
|
|
|
|
yield return new WaitForSeconds(maxWait + outroDuration);
|
|
}
|
|
|
|
private IEnumerator AnimateItemOut(MenuItem item)
|
|
{
|
|
yield return new WaitForSeconds(item.delay);
|
|
|
|
float time = 0f;
|
|
Vector2 startPos = item.rect.anchoredPosition;
|
|
Vector2 exitPos = item.targetPosition + new Vector2(moveDistance, 0f);
|
|
|
|
while (time < outroDuration)
|
|
{
|
|
time += Time.deltaTime;
|
|
float curved = ease.Evaluate(Mathf.Clamp01(time / outroDuration));
|
|
|
|
item.rect.anchoredPosition = Vector2.Lerp(startPos, exitPos, curved);
|
|
item.canvasGroup.alpha = Mathf.Lerp(1f, 0f, curved);
|
|
yield return null;
|
|
}
|
|
|
|
item.rect.anchoredPosition = exitPos;
|
|
item.canvasGroup.alpha = 0f;
|
|
item.canvasGroup.interactable = false;
|
|
item.canvasGroup.blocksRaycasts = false;
|
|
}
|
|
|
|
// ── 외부에서 재실행 ────────────────────────
|
|
public void ReplayIntro()
|
|
{
|
|
StopAllCoroutines();
|
|
|
|
foreach (MenuItem item in menuItems)
|
|
{
|
|
item.rect.anchoredPosition = item.targetPosition + new Vector2(moveDistance, 0f);
|
|
item.canvasGroup.alpha = 0f;
|
|
item.canvasGroup.interactable = false;
|
|
item.canvasGroup.blocksRaycasts = false;
|
|
}
|
|
|
|
StartCoroutine(PlayIntro());
|
|
}
|
|
} |