// Elfentier Screen Transitions (free download from elfentier.com) // 使い方: // 1. Canvas(Screen Space - Overlay) に全画面の RawImage を置く // 2. Elfentier/ScreenTransition シェーダーを使ったマテリアルを割り当てる // 3. この ScreenTransition コンポーネントを同じ GameObject に追加する // 4. ScreenTransition.Play(TransitionMode.CircleWipe, 0.6f, onComplete) を呼ぶ using System; using System.Collections; using UnityEngine; using UnityEngine.UI; namespace Elfentier.Transitions { public enum TransitionMode { Fade = 0, CircleWipe = 1, HorizontalWipe = 2, DiagonalBlinds = 3, } [RequireComponent(typeof(Graphic))] public sealed class ScreenTransition : MonoBehaviour { static readonly int ProgressId = Shader.PropertyToID("_Progress"); static readonly int ModeId = Shader.PropertyToID("_Mode"); [SerializeField] TransitionMode mode = TransitionMode.Fade; [SerializeField, Range(0.05f, 5f)] float duration = 0.6f; Graphic graphic; Material material; Coroutine running; void Awake() { graphic = GetComponent(); // 共有マテリアルを汚さないよう複製する material = new Material(graphic.material); graphic.material = material; material.SetFloat(ProgressId, 0f); graphic.raycastTarget = false; } /// 画面を覆う(シーン遷移の直前に呼ぶ) public void Play(Action onCovered = null) => Play(mode, duration, onCovered); public void Play(TransitionMode transitionMode, float seconds, Action onCovered = null) { if (running != null) StopCoroutine(running); material.SetFloat(ModeId, (float)transitionMode); running = StartCoroutine(Animate(0f, 1f, seconds, onCovered)); } /// 覆いを開ける(シーン読み込み後に呼ぶ) public void Reveal(Action onRevealed = null) => Reveal(mode, duration, onRevealed); public void Reveal(TransitionMode transitionMode, float seconds, Action onRevealed = null) { if (running != null) StopCoroutine(running); material.SetFloat(ModeId, (float)transitionMode); running = StartCoroutine(Animate(1f, 0f, seconds, onRevealed)); } IEnumerator Animate(float from, float to, float seconds, Action onComplete) { graphic.raycastTarget = true; float elapsed = 0f; while (elapsed < seconds) { elapsed += Time.unscaledDeltaTime; float t = Mathf.Clamp01(elapsed / seconds); // smoothstep で緩急をつける float eased = t * t * (3f - 2f * t); material.SetFloat(ProgressId, Mathf.Lerp(from, to, eased)); yield return null; } material.SetFloat(ProgressId, to); graphic.raycastTarget = to > 0.5f; running = null; onComplete?.Invoke(); } } }