湖州市网站建设_网站建设公司_色彩搭配_seo优化
2026/1/20 10:02:20 网站建设 项目流程

我在学习Tuanjie的过程中有过这样一个疑问:当我同一个模型资源需要在很多个Scene中使用,如果我给每个Scene中都放置一个GameObject,那么无疑会导致整个游戏的体积变得很大,那么有没有什么办法可以让这个模型资源可以被多个场景同时复用?

在Tuanjie 发布的Tower_Valley Demo中,有个名为Load Demo Scene的操作,点击该操作后多个零散Scene被加载到了一个名为Loader的Scene中最终叠加生成一个完整的Scene,并且这些场景可以随着游戏的运行动态加载以及卸载

image

 这样就很好的解决了我前面的疑问,可以将整个游戏拆分成很多个独立的Scene,并通过叠加的方式来达到实现不同的组合;比如:在A场景和B场景中玩家游戏对象可能是挖掘机、铲车、飞机等其中的任意一项,如果所有的模型资源全部放在A场景与B场景中,那么游戏体积将十分庞大,而使用这种叠加的方式,不仅可以减少游戏体积,也可以让玩家实现在游戏过程中的游戏对象切换;

 

那么究竟是如何实现的呢?

 

第一步:需要将所有需要加载的场景添加到Build Setting中,添加后可通过Scene的名称或索引来加载与卸载场景;

第二步:使用UnityEngine.SceneManagement命名空间下的SceneManager类实现加载,推荐使用异步加载;

AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);//核心是需要将加载模式设置成Additive

 

完整的代码:

 1 using UnityEngine;
 2 using UnityEngine.SceneManagement;
 3 using System.Collections;
 4 
 5 // 场景管理单例脚本,负责叠加加载/卸载场景
 6 public class SceneLoader : MonoBehaviour
 7 {
 8     // 单例实例,方便其他脚本调用
 9     public static SceneLoader Instance;
10 
11     private void Awake()
12     {
13         // 确保单例唯一
14         if (Instance == null)
15         {
16             Instance = this;
17             DontDestroyOnLoad(gameObject); // 切换场景时不销毁该脚本所在对象
18         }
19         else
20         {
21             Destroy(gameObject);
22         }
23     }
24 
25     // 异步叠加加载场景(通过场景名称)
26     public IEnumerator LoadSceneAdditive(string sceneName)
27     {
28         // 检查场景是否已加载,避免重复加载
29         if (SceneManager.GetSceneByName(sceneName).isLoaded)
30         {
31             Debug.LogWarning($"场景 {sceneName} 已加载,无需重复加载");
32             yield break;
33         }
34 
35         // 异步加载场景,指定Additive模式
36         AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
37 
38         // 加载过程中可以显示加载进度(比如UI进度条)
39         while (!asyncLoad.isDone)
40         {
41             float progress = Mathf.Clamp01(asyncLoad.progress / 0.9f); // Unity的progress到0.9才代表加载完成
42             Debug.Log($"加载进度:{progress * 100:F1}%");
43             yield return null;
44         }
45 
46         Debug.Log($"场景 {sceneName} 叠加加载完成");
47 
48         // 可选:设置某个场景为Active Scene(影响部分API的默认行为,比如Instantiate的默认父场景)
49         SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName));
50     }
51 
52     // 异步卸载场景
53     public IEnumerator UnloadScene(string sceneName)
54     {
55         // 检查场景是否存在
56         if (!SceneManager.GetSceneByName(sceneName).isLoaded)
57         {
58             Debug.LogWarning($"场景 {sceneName} 未加载,无需卸载");
59             yield break;
60         }
61 
62         AsyncOperation asyncUnload = SceneManager.UnloadSceneAsync(sceneName);
63         while (!asyncUnload.isDone)
64         {
65             yield return null;
66         }
67 
68         // 清理未使用的资源(可选,释放内存)
69         Resources.UnloadUnusedAssets();
70         Debug.Log($"场景 {sceneName} 卸载完成");
71     }
72 
73     // 快捷调用:加载多个场景(示例)
74     public void LoadAllGameScenes()
75     {
76         StartCoroutine(LoadSceneAdditive("Scene_MainUI")); // UI场景
77         StartCoroutine(LoadSceneAdditive("Scene_Terrain")); // 地形场景
78         StartCoroutine(LoadSceneAdditive("Scene_NPCs"));   // NPC场景
79     }
80 }

在需要加载场景的位置调用LoadAllGameScenes()即可

 注:Scene的异步加载可以在编辑模式下也可以在运行模式下,但是Scene的卸载只能在运行模式下

 

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询