UGF学习3-场景

场景组件的常用方法

  • 得到场景组件
    SceneComponent sceneComponent = GameEntry.GetComponent<SceneComponent>();

  • 加载场景

    • void LoadScene(string "路径名", int 加载优先级)
    • void LoadScene(string "路径名", int 加载优先级, object 用户数据)
    • void LoadScene(string "路径名")
    • void LoadScene(string "路径名", object 用户数据)
  • 卸载场景
    UnloadScene("场景名称");

    1
    2
    3
    4
    5
    6
     // 卸载所有场景()
    string[] loadedSceneAssetNames = Scene.GetLoadedSceneAssetNames();
    for (int i = 0; i < loadedSceneAssetNames.Length; i++)
    {
    Scene.UnloadScene(loadedSceneAssetNames[i]);
    }

    并不会卸载掉 GameFramework 启动场景

  • 场景回调

    • 方法一:
      订阅场景加载事件后回调(常用)
      常用场景加载事件:
      有关场景的事件API
      • LoadSceneDependencyAssetEventArgs
        加载场景时加载依赖资源事件
      • LoadSceneFailureEventArgs
        加载场景失败事件
      • LoadSceneSuccessEventArgs
        加载场景成功事件
      • LoadSceneUpdateEventArgs
        加载场景更新事件
      • UnloadSceneFailureEventArgs
        卸载场景失败事件
      • UnloadSceneSuccessEventArgs
        卸载场景成功事件
    • 方法二:
      使用 LoadSceneCallbacks (场景加载回调函数类)回调(不常用)
      LoadSceneCallbacks 介绍

场景组件机制

UGF在加载新场景时会将新场景叠加在原场景之上。
当多场景加载时会变得越来越乱,所以建议在加载新场景前先卸载所有场景,在加载。
卸载场景并不会卸载掉UGF的启动场景,可放心使用。

流程与场景的结合

在项目中一般会有专门的场景切换 流程 和记录场景数据的 数据表 来控制 场景 的切换。
流程 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using GameFramework.DataTable;
using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;

namespace YouProject {
public class ProcedureChangeScene : ProcedureBase
{
private const int MenuSceneId = 1;
private bool m_IsSceneLoadComplete = false;
private int m_BackgroundMusicId = 0;
private int sceneId = 0;

// 流程开始响应函数
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);

m_IsSceneLoadComplete = false;

// 订阅 场景加载成功事件 并绑定响应函数 OnLoadSceneSuccess
GameEntry.Event.Subscribe(LoadSceneSuccessEventArgs.EventId, OnLoadSceneSuccess);
// 订阅 场景加载失败事件 并绑定响应函数 OnLoadSceneFailure
GameEntry.Event.Subscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
// 订阅 初始化加载场景更新事件 并绑定响应函数 OnLoadSceneUpdate
GameEntry.Event.Subscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);

// 停止所有声音
GameEntry.Sound.StopAllLoadingSounds();
GameEntry.Sound.StopAllLoadedSounds();

// 隐藏所有实体
GameEntry.Entity.HideAllLoadingEntities();
GameEntry.Entity.HideAllLoadedEntities();

// 卸载所有场景
string[] loadedSceneAssetNames = GameEntry.Scene.GetLoadedSceneAssetNames();
for (int i = 0; i < loadedSceneAssetNames.Length; i++)
{
Debug.Log("loadedSceneAssetNames: " + loadedSceneAssetNames[i]);
GameEntry.Scene.UnloadScene(loadedSceneAssetNames[i]);
}

// 还原游戏速度
GameEntry.Base.ResetNormalGameSpeed();
// 从数据表中获取下个加载场景的ID
sceneId = procedureOwner.GetData<VarInt>("NextSceneId");
IDataTable<DRScene> dtScene = GameEntry.DataTable.GetDataTable<DRScene>();
DRScene drScene = dtScene.GetDataRow(sceneId);
if (drScene == null)
{
Log.Warning("Can not load scene '{0}' from data table.", sceneId.ToString());
return;
}
// 加载对应的场景
GameEntry.Scene.LoadScene(AssetUtility.GetSceneAsset(drScene.AssetName), Constant.AssetPriority.SceneAsset, this);
m_BackgroundMusicId = drScene.BackgroundMusicId;
}

// 流程结束响应函数
protected override void OnLeave(ProcedureOwner procedureOwner, bool isShutdown) {
GameEntry.Event.Unsubscribe(LoadSceneSuccessEventArgs.EventId, OnLoadSceneSuccess);
GameEntry.Event.Unsubscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
GameEntry.Event.Unsubscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);
GameEntry.Event.Unsubscribe(LoadSceneDependencyAssetEventArgs.EventId, OnLoadSceneDependencyAsset);

base.OnLeave(procedureOwner, isShutdown);
}

// 流程轮询函数
protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);

// 判断场景是否异步加载完成
if (!m_IsSceneLoadComplete)
return;

// 在这里根据切换到的场景编号进行对应的流程切换
switch (sceneId)
{
case 1:
ChangeState<ProcedureLogin>(procedureOwner);
break;
case 2:
ChangeState<ProcedureMain>(procedureOwner);
break;
case 3:
ChangeState<ProcedureBattle>(procedureOwner);
break;
default:
break;
}
}

// 场景加载成功事件响应函数
private void OnLoadSceneSuccess(object sender, GameEventArgs e)
{
LoadSceneSuccessEventArgs ne = (LoadSceneSuccessEventArgs)e;
// 若非本流程切换场景,不执行剩余操作
if (ne.UserData != this)
return;

Log.Info("Load scene '{0}' OK.", ne.SceneAssetName);

// 播放对应场景BGM
if (m_BackgroundMusicId > 0)
GameEntry.Sound.PlayMusic(m_BackgroundMusicId);

// 设置场景加载完成标志位为真
m_IsChangeSceneComplete = true;
}

// 场景加载失败事件响应函数
private void OnLoadSceneFailure(object sender, GameEventArgs e)
{
LoadSceneFailureEventArgs ne = (LoadSceneFailureEventArgs)e;
if (ne.UserData != this)
return;
Log.Error("Load scene '{0}' failure, error message '{1}'.", ne.SceneAssetName, ne.ErrorMessage);
}

// 场景加载使用资源更新事件响应函数
private void OnLoadSceneUpdate(object sender, GameEventArgs e)
{
LoadSceneUpdateEventArgs ne = (LoadSceneUpdateEventArgs)e;
if (ne.UserData != this)
return;
Log.Info("Load scene '{0}' update, progress '{1}'.", ne.SceneAssetName, ne.Progress.ToString("P2"));
}

// 场景加载依赖资源事件响应函数
private void OnLoadSceneDependencyAsset(object sender, GameEventArgs e)
{
LoadSceneDependencyAssetEventArgs ne = (LoadSceneDependencyAssetEventArgs)e;
if (ne.UserData != this)
return;
Log.Info("Load scene '{0}' dependency asset '{1}', count '{2}/{3}'.", ne.SceneAssetName, ne.DependencyAssetName, ne.LoadedCount.ToString(), ne.TotalCount.ToString());
}
}
}

对应的场景数据表