UGF切换场景是在原来的基础上叠加新的场景,在加载前需要卸载原来的场景,当然如果有叠加的需求,可以保留原来的场景。下面单独说一下场景的加载以及卸载。
场景加载
加载场景调用的是SceneComponent中的LoadScene方法。
/// <summary>
/// 加载场景。
/// </summary>
/// <param name="sceneAssetName">场景资源名称。</param>
/// <param name="priority">加载场景资源的优先级。</param>
/// <param name="userData">用户自定义数据。</param>
public void LoadScene(string sceneAssetName, int priority, object userData)
{
if (string.IsNullOrEmpty(sceneAssetName))
{
Log.Error("Scene asset name is invalid.");
return;
}
if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal))
{
Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName);
return;
}
m_SceneManager.LoadScene(sceneAssetName, priority, userData);
}
另外可以调用其他三个重写的方法,传入的参数会有变化,最终都会参数转换或使用默认参数调用上述方法。
public void LoadScene(string sceneAssetName)
public void LoadScene(string sceneAssetName, int priority)
public void LoadScene(string sceneAssetName, object userData)
我们可以看到sceneAssetName路径名是必传的参数。加载场景代码如下
//获取场景组件
SceneComponent sceneComponent=GameEntry.GetComponent<SceneComponent>();
//调用加载场景方法
sceneComponent.LoadScene("Assets/GameMain/Scenes/Main.unity");
再看一下Demo是怎么切换场景的:
Demo中将切换场景作为一个流程ProcedureChangeScene,进入流程后首先要做的是停止所有声音、影藏所有实体,卸载所有场景、还原游戏速度,当一切恢复如初后才会开始切换场景。这样做的好处显而易见,更便于统一管理场景切换时的初始化,还原等问题。不会因为写的太散而造成遗漏,我们也可以在切换场景时加入自己的逻辑。比如场景叠加时,可以根据初始化的逻辑自己另写一套。
Demo中场景的路径以及名称做了一层隔离,路径通过AssetUtility.GetSceneAsset调用,场景名称存储在数据表中,通过读取数据表来切换场景的名称。
当我们填完了场景名称配置表之后这就完了吗?不,还没有。我们场景编号是从哪来呢?
切换场景的流程流程中是通过GetData(“NextSceneId”)来获取场景编号
int sceneId = procedureOwner.GetData<VarInt32>("NextSceneId");
m_ChangeToMenu = sceneId == MenuSceneId;
IDataTable<DRScene> dtScene = GameEntry.DataTable.GetDataTable<DRScene>();
DRScene drScene = dtScene.GetDataRow(sceneId);
而调用场景切换流程前先通过SetData设置值。
procedureOwner.SetData<VarInt32>("NextSceneId", GameEntry.Config.GetInt("Scene.Menu"));
ChangeState<ProcedureChangeScene>(procedureOwner);
SetData和GetData等价于unity的PlayerPrefs方法保存在本地硬盘的键值对。NextSceneId保存的数据便是场景切换编号ID,ID的来源则是通过全局配置组件来获取。全局配置组件和配置文件在如下路径。
为了切换场景,添加了数据表以及全局配置表,是不是很麻烦?这个Demo游戏只有两个场景,而且这两个场景一毛一样,这不是闲的么。当然没有这么简单。
从Demo来看确实没必要这么麻烦,对于Demo这种单一玩法模式的游戏来说确实没必要。但是当我们的游戏扩展后,模式玩法场景大量增加的情况下,这样的管理就很有必要。例如这个场景配置表中只配置了背景音乐,如果场景不止天空,有地狱、桃花岛也有节奏光剑时,每个场景用到的飞行棋,特效都不一样,会有很多套。为了方便资源的组合配置,添加一张场景配置表是很有必要的。我们开发也不用去为了资源的切换组合来花费心思,直接把配置表交给策划来调整,我们只需要专注于游戏的玩法逻辑的开发。全局配置表也是同样的,如果有多种模式,简单、进阶、主线任务、支线任务等多种玩法时,玩法与场景的组合也可以交给策划任意配置,我们只管功能实现。
场景卸载
场景卸载,同样是通过场景资源的路径名称来卸载,即使我们按照Demo的卸载了所有的场景,也不会卸载掉我们框架所在的场景。
// 卸载所有场景
string[] loadedSceneAssetNames = GameEntry.Scene.GetLoadedSceneAssetNames();
for (int i = 0; i < loadedSceneAssetNames.Length; i++)
{
GameEntry.Scene.UnloadScene(loadedSceneAssetNames[i]);
}