274 lines
6.8 KiB
C#
274 lines
6.8 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public class gTransBlack : MonoBehaviour
|
|
{
|
|
[SerializeField] private Canvas b_Canvas;
|
|
[SerializeField] private CanvasGroup b_CG;
|
|
[SerializeField] private Text nowLoadingText;
|
|
[SerializeField] private int postSceneLoadCameraRefreshFrames = 12;
|
|
|
|
public Canvas Canvas => b_Canvas;
|
|
public CanvasGroup CanvasGroup => b_CG;
|
|
|
|
private Camera boundCamera;
|
|
private Coroutine cameraRefreshRoutine;
|
|
private int lastScreenWidth;
|
|
private int lastScreenHeight;
|
|
|
|
private void Awake()
|
|
{
|
|
EnsureReferences();
|
|
ConfigureCanvasForLetterbox();
|
|
ApplySceneCamera(true);
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
SceneManager.sceneLoaded -= HandleSceneLoaded;
|
|
SceneManager.sceneLoaded += HandleSceneLoaded;
|
|
SceneManager.activeSceneChanged -= HandleActiveSceneChanged;
|
|
SceneManager.activeSceneChanged += HandleActiveSceneChanged;
|
|
|
|
ConfigureCanvasForLetterbox();
|
|
StartCameraRefreshRoutine();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
SceneManager.sceneLoaded -= HandleSceneLoaded;
|
|
SceneManager.activeSceneChanged -= HandleActiveSceneChanged;
|
|
|
|
if (cameraRefreshRoutine != null)
|
|
{
|
|
StopCoroutine(cameraRefreshRoutine);
|
|
cameraRefreshRoutine = null;
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight || NeedsCameraRefresh())
|
|
{
|
|
ConfigureCanvasForLetterbox();
|
|
ApplySceneCamera(false);
|
|
}
|
|
}
|
|
|
|
private void HandleSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
StartCameraRefreshRoutine();
|
|
}
|
|
|
|
private void HandleActiveSceneChanged(Scene oldScene, Scene newScene)
|
|
{
|
|
StartCameraRefreshRoutine();
|
|
}
|
|
|
|
public void RefreshCanvasCamera()
|
|
{
|
|
ConfigureCanvasForLetterbox();
|
|
ApplySceneCamera(true);
|
|
StartCameraRefreshRoutine();
|
|
}
|
|
|
|
public void SetNowLoadingText(string text)
|
|
{
|
|
if (nowLoadingText != null)
|
|
{
|
|
nowLoadingText.text = text;
|
|
}
|
|
}
|
|
|
|
private void EnsureReferences()
|
|
{
|
|
if (b_Canvas == null)
|
|
{
|
|
b_Canvas = GetComponentInChildren<Canvas>(true);
|
|
}
|
|
|
|
if (b_CG == null)
|
|
{
|
|
b_CG = GetComponent<CanvasGroup>();
|
|
if (b_CG == null)
|
|
{
|
|
b_CG = GetComponentInChildren<CanvasGroup>(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ConfigureCanvasForLetterbox()
|
|
{
|
|
EnsureReferences();
|
|
|
|
if (b_Canvas == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (b_Canvas.renderMode != RenderMode.ScreenSpaceCamera)
|
|
{
|
|
b_Canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
|
}
|
|
|
|
if (b_Canvas.transform.localScale == Vector3.zero)
|
|
{
|
|
b_Canvas.transform.localScale = Vector3.one;
|
|
}
|
|
|
|
if (b_Canvas.planeDistance <= 0f)
|
|
{
|
|
b_Canvas.planeDistance = 100f;
|
|
}
|
|
|
|
b_Canvas.sortingOrder = short.MaxValue;
|
|
|
|
CanvasScaler scaler = b_Canvas.GetComponent<CanvasScaler>();
|
|
if (scaler != null)
|
|
{
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
|
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
|
// 锁高度缩放:分辨率跟随屏幕后,非 16:9 屏也能保证各 UI 层一致缩放、不错位。
|
|
scaler.matchWidthOrHeight = 1f;
|
|
}
|
|
}
|
|
|
|
private bool ApplySceneCamera(bool force)
|
|
{
|
|
EnsureReferences();
|
|
|
|
if (b_Canvas == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ConfigureCanvasForLetterbox();
|
|
|
|
Camera targetCamera = ResolveFirstSceneCamera();
|
|
if (targetCamera == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (force || b_Canvas.worldCamera != targetCamera || boundCamera != targetCamera)
|
|
{
|
|
b_Canvas.worldCamera = targetCamera;
|
|
boundCamera = targetCamera;
|
|
}
|
|
|
|
lastScreenWidth = Screen.width;
|
|
lastScreenHeight = Screen.height;
|
|
Canvas.ForceUpdateCanvases();
|
|
return true;
|
|
}
|
|
|
|
private bool NeedsCameraRefresh()
|
|
{
|
|
if (b_Canvas == null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (boundCamera == null || !boundCamera.isActiveAndEnabled)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (b_Canvas.renderMode != RenderMode.ScreenSpaceCamera)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return b_Canvas.worldCamera != boundCamera;
|
|
}
|
|
|
|
private void StartCameraRefreshRoutine()
|
|
{
|
|
if (!isActiveAndEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (cameraRefreshRoutine != null)
|
|
{
|
|
StopCoroutine(cameraRefreshRoutine);
|
|
}
|
|
|
|
cameraRefreshRoutine = StartCoroutine(RefreshCameraForSeveralFrames());
|
|
}
|
|
|
|
private IEnumerator RefreshCameraForSeveralFrames()
|
|
{
|
|
int frames = Mathf.Max(1, postSceneLoadCameraRefreshFrames);
|
|
for (int i = 0; i < frames; i++)
|
|
{
|
|
ApplySceneCamera(true);
|
|
yield return null;
|
|
}
|
|
|
|
yield return new WaitForEndOfFrame();
|
|
ApplySceneCamera(true);
|
|
cameraRefreshRoutine = null;
|
|
}
|
|
|
|
private static Camera ResolveFirstSceneCamera()
|
|
{
|
|
Scene activeScene = SceneManager.GetActiveScene();
|
|
Camera mainCam = Camera.main;
|
|
if (IsUsableSceneCamera(mainCam, activeScene, true))
|
|
{
|
|
return mainCam;
|
|
}
|
|
|
|
Camera[] cameras = Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
|
for (int i = 0; i < cameras.Length; i++)
|
|
{
|
|
Camera camera = cameras[i];
|
|
if (IsUsableSceneCamera(camera, activeScene, true))
|
|
{
|
|
return camera;
|
|
}
|
|
}
|
|
|
|
if (IsUsableSceneCamera(mainCam, activeScene, false))
|
|
{
|
|
return mainCam;
|
|
}
|
|
|
|
for (int i = 0; i < cameras.Length; i++)
|
|
{
|
|
Camera camera = cameras[i];
|
|
if (IsUsableSceneCamera(camera, activeScene, false))
|
|
{
|
|
return camera;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static bool IsUsableSceneCamera(Camera camera, Scene preferredScene, bool requirePreferredScene)
|
|
{
|
|
if (camera == null || !camera.isActiveAndEnabled)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Scene cameraScene = camera.gameObject.scene;
|
|
if (!cameraScene.IsValid() || !cameraScene.isLoaded)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (requirePreferredScene && cameraScene != preferredScene)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|