206 lines
6.9 KiB
C#
206 lines
6.9 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public static class BgmRuntimeBootstrap
|
|
{
|
|
private const string RuntimeAudioListenerName = "__RuntimeAudioListener";
|
|
private static readonly List<Transform> _transformBuffer = new List<Transform>(512);
|
|
private static readonly List<Transform> _transformStack = new List<Transform>(512);
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
private static void Bootstrap()
|
|
{
|
|
var mgr = BgmPlaybackManager.EnsureInstance();
|
|
var controller = SceneObjectLookupCache.FindAny<btmandtopController>();
|
|
if (controller != null && controller.bgmMixerGroup != null)
|
|
{
|
|
mgr.SetOutputMixerGroup(controller.bgmMixerGroup);
|
|
}
|
|
mgr.EnsurePlaying();
|
|
EnsureAudioListener(SceneManager.GetActiveScene());
|
|
|
|
// Ensure UI binder exists
|
|
if (SceneObjectLookupCache.FindAny<BgmUiBinder>() == null)
|
|
{
|
|
var go = new GameObject("BGM_UI_Binder");
|
|
go.AddComponent<BgmUiBinder>();
|
|
Object.DontDestroyOnLoad(go);
|
|
}
|
|
|
|
RemoveBgmParticlesInLoadedScenes();
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
}
|
|
|
|
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
EnsureAudioListener(scene);
|
|
var mgr = BgmPlaybackManager.Instance ?? BgmPlaybackManager.EnsureInstance();
|
|
mgr.EnsurePlaying();
|
|
RemoveBgmParticlesInLoadedScenes();
|
|
}
|
|
|
|
private static void RemoveBgmParticlesInLoadedScenes()
|
|
{
|
|
int sceneCount = SceneManager.sceneCount;
|
|
for (int i = 0; i < sceneCount; i++)
|
|
{
|
|
var scene = SceneManager.GetSceneAt(i);
|
|
if (!scene.IsValid() || !scene.isLoaded) continue;
|
|
RemoveBgmParticlesInScene(scene);
|
|
}
|
|
}
|
|
|
|
private static void RemoveBgmParticlesInScene(Scene scene)
|
|
{
|
|
var emitters = Object.FindObjectsByType<BgmParticleEmitter>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
for (int i = 0; i < emitters.Length; i++)
|
|
{
|
|
var e = emitters[i];
|
|
if (e == null) continue;
|
|
if (!e.gameObject.scene.IsValid() || !e.gameObject.scene.isLoaded) continue;
|
|
Object.Destroy(e.gameObject);
|
|
}
|
|
|
|
CollectTransformsInScene(scene, _transformBuffer);
|
|
for (int i = 0; i < _transformBuffer.Count; i++)
|
|
{
|
|
var t = _transformBuffer[i];
|
|
if (t == null || t.gameObject.scene != scene) continue;
|
|
if (t.name.Equals("BgmParticles", System.StringComparison.OrdinalIgnoreCase))
|
|
Object.Destroy(t.gameObject);
|
|
}
|
|
}
|
|
|
|
private static void EnsureAudioListener(Scene scene)
|
|
{
|
|
if (!scene.IsValid() || !scene.isLoaded)
|
|
return;
|
|
|
|
AudioListener[] allListeners = Object.FindObjectsByType<AudioListener>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
|
|
AudioListener activeEnabledInScene = null;
|
|
AudioListener activeInScene = null;
|
|
AudioListener anyInScene = null;
|
|
|
|
for (int i = 0; i < allListeners.Length; i++)
|
|
{
|
|
AudioListener listener = allListeners[i];
|
|
if (listener == null)
|
|
continue;
|
|
if (!listener.gameObject.scene.IsValid() || listener.gameObject.scene != scene)
|
|
continue;
|
|
|
|
if (anyInScene == null)
|
|
anyInScene = listener;
|
|
|
|
if (listener.gameObject.activeInHierarchy && activeInScene == null)
|
|
activeInScene = listener;
|
|
|
|
if (listener.gameObject.activeInHierarchy && listener.enabled)
|
|
{
|
|
activeEnabledInScene = listener;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (activeEnabledInScene != null)
|
|
return;
|
|
|
|
if (activeInScene != null)
|
|
{
|
|
activeInScene.enabled = true;
|
|
return;
|
|
}
|
|
|
|
if (anyInScene != null)
|
|
{
|
|
anyInScene.enabled = true;
|
|
return;
|
|
}
|
|
|
|
Camera cameraInScene = FindBestCameraInScene(scene);
|
|
if (cameraInScene != null)
|
|
{
|
|
AudioListener cameraListener = cameraInScene.GetComponent<AudioListener>();
|
|
if (cameraListener == null)
|
|
cameraListener = cameraInScene.gameObject.AddComponent<AudioListener>();
|
|
cameraListener.enabled = true;
|
|
return;
|
|
}
|
|
|
|
GameObject listenerRoot = FindNamedObjectInScene(scene, RuntimeAudioListenerName);
|
|
if (listenerRoot == null)
|
|
{
|
|
listenerRoot = new GameObject(RuntimeAudioListenerName);
|
|
try { SceneManager.MoveGameObjectToScene(listenerRoot, scene); } catch { }
|
|
}
|
|
if (listenerRoot.GetComponent<AudioListener>() == null)
|
|
listenerRoot.AddComponent<AudioListener>();
|
|
}
|
|
|
|
private static Camera FindBestCameraInScene(Scene scene)
|
|
{
|
|
Camera[] cameras = Object.FindObjectsByType<Camera>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
Camera first = null;
|
|
for (int i = 0; i < cameras.Length; i++)
|
|
{
|
|
Camera cam = cameras[i];
|
|
if (cam == null || cam.gameObject.scene != scene)
|
|
continue;
|
|
|
|
if (first == null)
|
|
first = cam;
|
|
|
|
if (cam.gameObject.activeInHierarchy && cam.enabled && cam.CompareTag("MainCamera"))
|
|
return cam;
|
|
}
|
|
|
|
if (first != null)
|
|
return first;
|
|
return null;
|
|
}
|
|
|
|
private static GameObject FindNamedObjectInScene(Scene scene, string objectName)
|
|
{
|
|
if (string.IsNullOrEmpty(objectName))
|
|
return null;
|
|
|
|
CollectTransformsInScene(scene, _transformBuffer);
|
|
for (int i = 0; i < _transformBuffer.Count; i++)
|
|
{
|
|
var t = _transformBuffer[i];
|
|
if (t == null || t.gameObject.scene != scene) continue;
|
|
if (string.Equals(t.name, objectName, System.StringComparison.OrdinalIgnoreCase)) return t.gameObject;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static void CollectTransformsInScene(Scene scene, List<Transform> buffer)
|
|
{
|
|
buffer.Clear();
|
|
_transformStack.Clear();
|
|
var roots = scene.GetRootGameObjects();
|
|
for (int i = 0; i < roots.Length; i++)
|
|
{
|
|
var root = roots[i];
|
|
if (root == null) continue;
|
|
_transformStack.Add(root.transform);
|
|
while (_transformStack.Count > 0)
|
|
{
|
|
int last = _transformStack.Count - 1;
|
|
var t = _transformStack[last];
|
|
_transformStack.RemoveAt(last);
|
|
if (t == null) continue;
|
|
buffer.Add(t);
|
|
int childCount = t.childCount;
|
|
for (int c = 0; c < childCount; c++)
|
|
{
|
|
_transformStack.Add(t.GetChild(c));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|