2025-12-02 16:04:23 +08:00

229 lines
6.4 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>();
//this.Error(childCanvas.transform.name);
// 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, .1f);
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);
}
}
}
}