using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; namespace BNG { public class ScreenFader : MonoBehaviour { [Tooltip("Should the screen fade in when a new level is loaded")] public bool FadeOnSceneLoaded = true; [Tooltip("Color of the fade. Alpha will be modified when fading in / out")] public Color FadeColor = Color.black; [Tooltip("How fast to fade in / out")] public float FadeInSpeed = 6f; public float FadeOutSpeed = 6f; [Tooltip("Wait X seconds before fading scene in")] public float SceneFadeInDelay = 1f; GameObject fadeObject; RectTransform fadeObjectRect; Canvas fadeCanvas; CanvasGroup canvasGroup; Image fadeImage; IEnumerator fadeRoutine; string faderName = "ScreenFader"; void Awake() { initialize(); } protected virtual void initialize() { // Create a Canvas that will be placed directly over the camera if (fadeObject == null) { Canvas childCanvas = GetComponentInChildren(); // Found existing item, no need to initialize this one if (childCanvas != null && childCanvas.transform.name == faderName) { GameObject.Destroy(this.gameObject); return; } fadeObject = new GameObject(); fadeObject.transform.parent = Camera.main.transform; fadeObject.transform.localPosition = new Vector3(0, 0, 0.03f); fadeObject.transform.localEulerAngles = Vector3.zero; fadeObject.transform.name = faderName; fadeCanvas = fadeObject.AddComponent(); fadeCanvas.renderMode = RenderMode.WorldSpace; fadeCanvas.sortingOrder = 100; // Make sure the canvas renders on top canvasGroup = fadeObject.AddComponent(); canvasGroup.interactable = false; fadeImage = fadeObject.AddComponent(); fadeImage.color = FadeColor; fadeImage.raycastTarget = false; // Stretch the image fadeObjectRect = fadeObject.GetComponent(); fadeObjectRect.anchorMin = new Vector2(1, 0); fadeObjectRect.anchorMax = new Vector2(0, 1); fadeObjectRect.pivot = new Vector2(0.5f, 0.5f); fadeObjectRect.sizeDelta = new Vector2(0.2f, 0.2f); fadeObjectRect.localScale = new Vector2(2f, 2f); } } void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (FadeOnSceneLoaded && fadeObject != null) { // Start screen at fade updateImageAlpha(FadeColor.a); StartCoroutine(fadeOutWithDelay(SceneFadeInDelay)); } } IEnumerator fadeOutWithDelay(float delaySeconds) { yield return new WaitForSeconds(delaySeconds); DoFadeOut(); } /// /// Fade from transparent to solid color /// public virtual void DoFadeIn() { // Stop if currently running if (fadeRoutine != null) { StopCoroutine(fadeRoutine); } // Do the fade routine if (canvasGroup != null) { fadeRoutine = doFade(canvasGroup.alpha, 1); StartCoroutine(fadeRoutine); } } /// /// Fade from solid color to transparent /// public virtual void DoFadeOut() { if (fadeRoutine != null) { StopCoroutine(fadeRoutine); } fadeRoutine = doFade(canvasGroup.alpha, 0); StartCoroutine(fadeRoutine); } public virtual void SetFadeLevel(float fadeLevel) { if (fadeRoutine != null) { StopCoroutine(fadeRoutine); // Debug.Log("----- Stopped Routine"); } // No Canvas available to fade if (canvasGroup == null) { return; } fadeRoutine = doFade(canvasGroup.alpha, fadeLevel); StartCoroutine(fadeRoutine); } IEnumerator doFade(float alphaFrom, float alphaTo) { float alpha = alphaFrom; updateImageAlpha(alpha); while (alpha != alphaTo) { if (alphaFrom < alphaTo) { alpha += Time.deltaTime * FadeInSpeed; if (alpha > alphaTo) { alpha = alphaTo; } } else { alpha -= Time.deltaTime * FadeOutSpeed; if (alpha < alphaTo) { alpha = alphaTo; } } updateImageAlpha(alpha); yield return new WaitForEndOfFrame(); } yield return new WaitForEndOfFrame(); // Ensure alpha is always applied updateImageAlpha(alphaTo); } protected virtual void updateImageAlpha(float alphaValue) { // Canvas Group was Destroyed. if (canvasGroup == null) { return; } // Enable canvas if necessary if (!canvasGroup.gameObject.activeSelf) { canvasGroup.gameObject.SetActive(true); } canvasGroup.alpha = alphaValue; // Disable Canvas if we're done if (alphaValue == 0 && canvasGroup.gameObject.activeSelf) { canvasGroup.gameObject.SetActive(false); } } } }