Files
bansonic_beta_main/Assets/scripts/Audio/BgmRuntimeBootstrap.cs
T

162 lines
5.3 KiB
C#

using UnityEngine;
using UnityEngine.SceneManagement;
public static class BgmRuntimeBootstrap
{
private const string RuntimeAudioListenerName = "__RuntimeAudioListener";
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
private static void Bootstrap()
{
var mgr = BgmPlaybackManager.EnsureInstance();
mgr.EnsurePlaying();
EnsureAudioListener(SceneManager.GetActiveScene());
// Ensure UI binder exists
if (Object.FindAnyObjectByType<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);
RemoveBgmParticlesInLoadedScenes();
}
private static void RemoveBgmParticlesInLoadedScenes()
{
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);
}
var all = Resources.FindObjectsOfTypeAll<Transform>();
for (int i = 0; i < all.Length; i++)
{
var t = all[i];
if (t == null) continue;
if (!t.gameObject.scene.IsValid() || !t.gameObject.scene.isLoaded) 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;
Transform[] all = Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
for (int i = 0; i < all.Length; i++)
{
Transform t = all[i];
if (t == null || t.gameObject.scene != scene)
continue;
if (string.Equals(t.name, objectName, System.StringComparison.OrdinalIgnoreCase))
return t.gameObject;
}
return null;
}
}