rabidus-test/Assets/BNG Framework/Scripts/Components/ScreenFader.cs

198 lines
6.0 KiB
C#

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<Canvas>();
// 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<Canvas>();
fadeCanvas.renderMode = RenderMode.WorldSpace;
fadeCanvas.sortingOrder = 100; // Make sure the canvas renders on top
canvasGroup = fadeObject.AddComponent<CanvasGroup>();
canvasGroup.interactable = false;
fadeImage = fadeObject.AddComponent<Image>();
fadeImage.color = FadeColor;
fadeImage.raycastTarget = false;
// Stretch the image
fadeObjectRect = fadeObject.GetComponent<RectTransform>();
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();
}
/// <summary>
/// Fade from transparent to solid color
/// </summary>
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);
}
}
/// <summary>
/// Fade from solid color to transparent
/// </summary>
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);
}
}
}
}