162 lines
4.5 KiB
C#
162 lines
4.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public static class SceneObjectLookupCache
|
|
{
|
|
private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>(StringComparer.Ordinal);
|
|
private static readonly Dictionary<Type, UnityEngine.Object> AnyTypeCache = new Dictionary<Type, UnityEngine.Object>();
|
|
private static readonly Dictionary<Type, UnityEngine.Object> FirstTypeCache = new Dictionary<Type, UnityEngine.Object>();
|
|
private static bool hooked;
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
|
private static void ResetStaticState()
|
|
{
|
|
Cache.Clear();
|
|
AnyTypeCache.Clear();
|
|
FirstTypeCache.Clear();
|
|
hooked = false;
|
|
}
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
|
private static void Bootstrap()
|
|
{
|
|
if (hooked)
|
|
return;
|
|
|
|
hooked = true;
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
SceneManager.activeSceneChanged -= OnActiveSceneChanged;
|
|
SceneManager.activeSceneChanged += OnActiveSceneChanged;
|
|
}
|
|
|
|
public static GameObject Find(string nameOrPath)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(nameOrPath))
|
|
return null;
|
|
|
|
string key = nameOrPath.Trim();
|
|
if (Cache.TryGetValue(key, out GameObject cached))
|
|
{
|
|
if (IsUsableCachedGameObject(cached, key))
|
|
return cached;
|
|
|
|
Cache.Remove(key);
|
|
}
|
|
|
|
GameObject found = GameObject.Find(key);
|
|
if (found != null)
|
|
Cache[key] = found;
|
|
return found;
|
|
}
|
|
|
|
public static T FindComponent<T>(string nameOrPath) where T : Component
|
|
{
|
|
GameObject go = Find(nameOrPath);
|
|
return go != null ? go.GetComponent<T>() : null;
|
|
}
|
|
|
|
public static T FindAny<T>() where T : UnityEngine.Object
|
|
{
|
|
var type = typeof(T);
|
|
if (AnyTypeCache.TryGetValue(type, out var cached))
|
|
{
|
|
if (IsUsableCachedObject(cached))
|
|
return cached as T;
|
|
|
|
AnyTypeCache.Remove(type);
|
|
}
|
|
|
|
T found = UnityEngine.Object.FindAnyObjectByType<T>();
|
|
if (found != null)
|
|
AnyTypeCache[type] = found;
|
|
return found;
|
|
}
|
|
|
|
public static T FindFirst<T>() where T : UnityEngine.Object
|
|
{
|
|
var type = typeof(T);
|
|
if (FirstTypeCache.TryGetValue(type, out var cached))
|
|
{
|
|
if (IsUsableCachedObject(cached))
|
|
return cached as T;
|
|
|
|
FirstTypeCache.Remove(type);
|
|
}
|
|
|
|
T found = UnityEngine.Object.FindFirstObjectByType<T>();
|
|
if (found != null)
|
|
FirstTypeCache[type] = found;
|
|
return found;
|
|
}
|
|
|
|
public static Transform FindTransform(string nameOrPath)
|
|
{
|
|
GameObject go = Find(nameOrPath);
|
|
return go != null ? go.transform : null;
|
|
}
|
|
|
|
public static void Clear()
|
|
{
|
|
Cache.Clear();
|
|
AnyTypeCache.Clear();
|
|
FirstTypeCache.Clear();
|
|
}
|
|
|
|
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
Cache.Clear();
|
|
AnyTypeCache.Clear();
|
|
FirstTypeCache.Clear();
|
|
}
|
|
|
|
private static void OnActiveSceneChanged(Scene oldScene, Scene newScene)
|
|
{
|
|
Cache.Clear();
|
|
AnyTypeCache.Clear();
|
|
FirstTypeCache.Clear();
|
|
}
|
|
|
|
private static bool IsUsableCachedObject(UnityEngine.Object cached)
|
|
{
|
|
if (cached == null)
|
|
return false;
|
|
|
|
if (cached is Component component)
|
|
return component != null && component.gameObject != null && component.gameObject.activeInHierarchy;
|
|
|
|
if (cached is GameObject go)
|
|
return go.activeInHierarchy;
|
|
|
|
return true;
|
|
}
|
|
|
|
private static bool IsUsableCachedGameObject(GameObject cached, string key)
|
|
{
|
|
if (cached == null || !cached.activeInHierarchy)
|
|
return false;
|
|
|
|
int slashIndex = key.IndexOf('/');
|
|
if (slashIndex < 0)
|
|
return cached.name == key;
|
|
|
|
return BuildHierarchyPath(cached.transform) == key;
|
|
}
|
|
|
|
private static string BuildHierarchyPath(Transform transform)
|
|
{
|
|
if (transform == null)
|
|
return string.Empty;
|
|
|
|
var path = transform.name;
|
|
while (transform.parent != null)
|
|
{
|
|
transform = transform.parent;
|
|
path = transform.name + "/" + path;
|
|
}
|
|
return path;
|
|
}
|
|
}
|