点击按钮加载新场景后,如何将Prefab实例化到新场景或指定场景?
这个问题我之前帮人排查过好几次,核心原因是Unity默认会在当前激活的Scene中实例化对象——如果你加载新Scene的时机和实例化的时机没配合好,Prefab就会“留在”旧Scene里。下面给你两种最常用的解决方案,分同步和异步加载场景的情况:
解决方案1:同步加载场景时实例化到新Scene
如果你的场景是同步加载(直接替换当前场景),可以先完成场景加载,切换激活场景后再实例化,或者手动把实例化的对象移动到新场景:
using UnityEngine; using UnityEngine.SceneManagement; public class SceneSpawner : MonoBehaviour { // 在Inspector中拖入你要生成的Prefab public GameObject targetPrefab; // 目标场景的名称 public string newSceneName; public void OnButtonClick() { // 同步加载新场景(默认是Single模式,替换当前场景) SceneManager.LoadScene(newSceneName); // 获取刚加载的新场景 Scene newScene = SceneManager.GetSceneByName(newSceneName); // 确保新场景被设置为当前激活场景 SceneManager.SetActiveScene(newScene); // 实例化Prefab,此时会自动在激活场景中创建 Instantiate(targetPrefab); // 更稳妥的方式:如果实例化后发现还在旧场景,手动移动过去 // GameObject spawnedObj = Instantiate(targetPrefab); // SceneManager.MoveGameObjectToScene(spawnedObj, newScene); } }
解决方案2:异步加载场景时实例化到新Scene
如果是异步加载场景(避免卡顿),必须等场景加载完成后再处理实例化,不然新场景还没准备好:
using UnityEngine; using UnityEngine.SceneManagement; using System.Collections; public class AsyncSceneSpawner : MonoBehaviour { public GameObject targetPrefab; public string newSceneName; public void OnButtonClick() { StartCoroutine(LoadAndSpawn()); } private IEnumerator LoadAndSpawn() { // 异步加载新场景,这里用Single模式,Additive模式请修改第二个参数 AsyncOperation loadOp = SceneManager.LoadSceneAsync(newSceneName); // 等待场景加载完成 while (!loadOp.isDone) { yield return null; } // 获取加载完成的新场景 Scene newScene = SceneManager.GetSceneByName(newSceneName); // 实例化Prefab GameObject spawnedObj = Instantiate(targetPrefab); // 将实例化的对象移动到新场景中 SceneManager.MoveGameObjectToScene(spawnedObj, newScene); // 如果是Additive模式加载多场景,记得手动激活新场景 // SceneManager.SetActiveScene(newScene); } }
额外注意事项
- 如果是Additive模式加载多场景,一定要明确用
SceneManager.MoveGameObjectToScene()指定目标场景,因为默认会在当前活跃场景创建对象。 - 不要给Prefab设置
DontDestroyOnLoad,否则它会脱离场景层级,不会归属于任何场景。 - 也可以直接把Prefab实例化到新场景的根对象下,比如:
Instantiate(targetPrefab, newScene.GetRootGameObjects()[0].transform);,这样也会自动归属到新场景。
内容的提问来源于stack exchange,提问作者Issam Otoz
相关产品推荐
相关产品推荐

