如何从DontDestroyOnLoad脚本访问其他加载场景中的游戏对象?
问题排查与解决方案
核心问题排查
敌人对象活跃状态:
FindObjectsOfType<T>()默认仅搜索Active状态的对象。如果敌人或其父节点被设置为非Active,需传入第二个参数true来包含非活跃对象:foreach(Enemy enemy in FindObjectsOfType<Enemy>(true)) { // 执行你的逻辑 }场景加载时机:如果查找逻辑在场景加载完成前执行(比如玩家脚本的
Awake阶段),此时敌人还未实例化,自然找不到。建议将查找逻辑绑定到场景加载完成事件:private void OnEnable() { SceneManager.sceneLoaded += HandleSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= HandleSceneLoaded; } private void HandleSceneLoaded(Scene loadedScene, LoadSceneMode loadMode) { // 场景加载完成后再执行查找 foreach(Enemy enemy in FindObjectsOfType<Enemy>(true)) { // 执行你的逻辑 } }
可靠的跨场景敌人管理方案
如果上述排查无效,推荐用全局敌人管理器单例统一管理,比手动查找更稳定:
创建
EnemyManager单例脚本:public class EnemyManager : MonoBehaviour { public static EnemyManager Instance; public List<Enemy> AllEnemies = new List<Enemy>(); private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } public void RegisterEnemy(Enemy enemy) { if (!AllEnemies.Contains(enemy)) AllEnemies.Add(enemy); } public void UnregisterEnemy(Enemy enemy) { AllEnemies.Remove(enemy); } }在
Enemy脚本中注册/注销自身:private void Start() { EnemyManager.Instance.RegisterEnemy(this); } private void OnDestroy() { if (EnemyManager.Instance != null) EnemyManager.Instance.UnregisterEnemy(this); }玩家脚本中直接访问管理器的敌人列表:
foreach(Enemy enemy in EnemyManager.Instance.AllEnemies) { // 执行你的逻辑 }
手动遍历所有加载场景的方法
如果不想用单例,也可以直接遍历所有已加载场景的根对象,确保不会遗漏任何场景的敌人:
foreach (Scene scene in SceneManager.GetAllScenes()) { if (!scene.isLoaded) continue; GameObject[] rootObjects = scene.GetRootGameObjects(); foreach (GameObject root in rootObjects) { // 递归查找所有子对象中的Enemy,包括非活跃的 Enemy[] enemies = root.GetComponentsInChildren<Enemy>(true); foreach (Enemy enemy in enemies) { // 执行你的逻辑 } } }
内容的提问来源于stack exchange,提问作者Legendized
相关产品推荐
相关产品推荐

