怎样保证ngui界面跳转不消失,也就是管理多个界面,现在我们就来看看过程。
主要的做法就是:将所有的界面都放在A场景中,游戏一开始先加载场景A,然后所有的界面(UIRoot)都在同一个游戏对象下(比如叫AllUIGameObject),然后在代码里DontDestroyOnLoad(AllGameObject),这样切换到其他场景(B、C、D)时,界面可以得以继续存在,如果再返回A场景(比如切换账号回到登陆界面的情况下),这个时候因为又要重头开始走登陆的流程,上一个账号的数据很多都无效了,因此Destroy掉前面的AllUIGameObject对象(当然有一些角色的数据如果用了static或者单体等保存下来的话,还是要动态的去重置的),再重新按照上述的步骤加载场景A走相同的流程就可以了(这里的指的流程简单的就指下面的LaunchGame.cs脚本中的start()函数)。
因为使用DestroyOnLoad(Obj),来回切换obj所在的场景时,会出现多份Obj的克隆,为此,在网上搜了一些方法,比如用个标志位来判断是否已经克隆,或者用单例判断Obj是否已经被初始化过,但都一样会出现重复Obj的情况!因此改为了上述所说的思路。
LaunchGame.cs:
1 using UnityEngine;
2
3 public class LaunchGame : MonoBehaviour
4 {
5 public GameObject mAllUIGameObject = null;
6
7 private static LaunchGame mInstance = null;
8 public static LaunchGame Instance
9 {
10 get
11 {
12 return mInstance;
13 }
14 private set
15 {
16
17 }
18 }
19 void Start ()
20 {
21 if (mInstance == null)
22 {
23 Output.Log("LaunchGame.Start(), mInstance == null");
24 mInstance = this;
25 }
26
27 DontDestroyOnLoad(mAllUIGameObject);
28
29 UIManager.Instance.Init();
30
31 Output.Log("LaunchGame.Start()");
32 }
33
34 void Update ()
35 {
36
37 }
38
39 public void DestroyAllUIGameObject()
40 {
41 Destroy(mAllUIGameObject);
42 }
1 using System.Collections.Generic;
2
3 // 面板类型
4 public enum UIType
5 {
6 UI1,
7 UI2,
8 UI3,
9 UI4,
10 }
11
12 // 界面逻辑管理器
13 public class UIManager : Singleton<UIManager>
14 {
15 public UI1 ui1 = null;
16 public UI2 ui2 = null;
17 public UI3 ui3 = null;
18 public UI4 ui4 = null;
19
20 Dictionary<UIType, UIBase> mUIDic = new Dictionary<UIType, UIBase>();
21
22 // 初始化界面逻辑
23 public void Init()
24 {
25 CheckMembers();
26 InitAllPanel();
27 }
28
29 // 检测成员变量是否有效
30 void CheckMembers()
31 {
32 Assert.IsNotNull(ui1, "UIManager.CheckMembers(), ui1 is null object!");
33 Assert.IsNotNull(ui2, "UIManager.CheckMembers(), ui2 is null object!");
34 Assert.IsNotNull(ui3, "UIManager.CheckMembers(), ui3 is null object!");
35 Assert.IsNotNull(ui4, "UIManager.CheckMembers(), ui4 is null object!");
36 }
37
38 // 初始化所有面板
39 void InitAllPanel()
40 {
41 mUIDic.Add(UIType.UI1, ui1);
42 mUIDic.Add(UIType.UI2, ui2);
43 mUIDic.Add(UIType.UI3, ui3);
44 mUIDic.Add(UIType.UI4, ui4);
45
46 foreach (UIBase ui in mUIDic.Values)
47 {
48 if (ui.m_panel != null)
49 {
50 ui.CheckWidget();
51 ui.Init();
52 ui.BindingEvent();
53 ui.Reset();
54 }
55 }
56 }
57
58 // 显示指定面板
59 public void ShowPanel(UIType type)
60 {
61 foreach (KeyValuePair<UIType, UIBase> item in mUIDic)
62 {
63 if (type == item.Key)
64 {
65 item.Value.Show();
66 }
67 else
68 {
69 item.Value.Hide();
70 }
71 }
72 }
73 }
其他脚本(诸如UI1..UI4、UIBase)就不贴了,都没什么,在SceneA->SceneB->SceneC都是用Application.LoadLevel(),而在Scene X -> SceneA之前,就会调用LaunchGame.cs中的函数DestroyAllUIGameObject(),然后才LoadLevel(场景A)。
主要的做法就是:将所有的界面都放在A场景中,游戏一开始先加载场景A,然后所有的界面(UIRoot)都在同一个游戏对象下(比如叫AllUIGameObject),然后在代码里DontDestroyOnLoad(AllGameObject),这样切换到其他场景(B、C、D)时,界面可以得以继续存在,如果再返回A场景(比如切换账号回到登陆界面的情况下),这个时候因为又要重头开始走登陆的流程,上一个账号的数据很多都无效了,因此Destroy掉前面的AllUIGameObject对象(当然有一些角色的数据如果用了static或者单体等保存下来的话,还是要动态的去重置的),再重新按照上述的步骤加载场景A走相同的流程就可以了(这里的指的流程简单的就指下面的LaunchGame.cs脚本中的start()函数)。
因为使用DestroyOnLoad(Obj),来回切换obj所在的场景时,会出现多份Obj的克隆,为此,在网上搜了一些方法,比如用个标志位来判断是否已经克隆,或者用单例判断Obj是否已经被初始化过,但都一样会出现重复Obj的情况!因此改为了上述所说的思路。
LaunchGame.cs:
1 using UnityEngine;
2
3 public class LaunchGame : MonoBehaviour
4 {
5 public GameObject mAllUIGameObject = null;
6
7 private static LaunchGame mInstance = null;
8 public static LaunchGame Instance
9 {
10 get
11 {
12 return mInstance;
13 }
14 private set
15 {
16
17 }
18 }
19 void Start ()
20 {
21 if (mInstance == null)
22 {
23 Output.Log("LaunchGame.Start(), mInstance == null");
24 mInstance = this;
25 }
26
27 DontDestroyOnLoad(mAllUIGameObject);
28
29 UIManager.Instance.Init();
30
31 Output.Log("LaunchGame.Start()");
32 }
33
34 void Update ()
35 {
36
37 }
38
39 public void DestroyAllUIGameObject()
40 {
41 Destroy(mAllUIGameObject);
42 }
43 }
UIManager.cs:1 using System.Collections.Generic;
2
3 // 面板类型
4 public enum UIType
5 {
6 UI1,
7 UI2,
8 UI3,
9 UI4,
10 }
11
12 // 界面逻辑管理器
13 public class UIManager : Singleton<UIManager>
14 {
15 public UI1 ui1 = null;
16 public UI2 ui2 = null;
17 public UI3 ui3 = null;
18 public UI4 ui4 = null;
19
20 Dictionary<UIType, UIBase> mUIDic = new Dictionary<UIType, UIBase>();
21
22 // 初始化界面逻辑
23 public void Init()
24 {
25 CheckMembers();
26 InitAllPanel();
27 }
28
29 // 检测成员变量是否有效
30 void CheckMembers()
31 {
32 Assert.IsNotNull(ui1, "UIManager.CheckMembers(), ui1 is null object!");
33 Assert.IsNotNull(ui2, "UIManager.CheckMembers(), ui2 is null object!");
34 Assert.IsNotNull(ui3, "UIManager.CheckMembers(), ui3 is null object!");
35 Assert.IsNotNull(ui4, "UIManager.CheckMembers(), ui4 is null object!");
36 }
37
38 // 初始化所有面板
39 void InitAllPanel()
40 {
41 mUIDic.Add(UIType.UI1, ui1);
42 mUIDic.Add(UIType.UI2, ui2);
43 mUIDic.Add(UIType.UI3, ui3);
44 mUIDic.Add(UIType.UI4, ui4);
45
46 foreach (UIBase ui in mUIDic.Values)
47 {
48 if (ui.m_panel != null)
49 {
50 ui.CheckWidget();
51 ui.Init();
52 ui.BindingEvent();
53 ui.Reset();
54 }
55 }
56 }
57
58 // 显示指定面板
59 public void ShowPanel(UIType type)
60 {
61 foreach (KeyValuePair<UIType, UIBase> item in mUIDic)
62 {
63 if (type == item.Key)
64 {
65 item.Value.Show();
66 }
67 else
68 {
69 item.Value.Hide();
70 }
71 }
72 }
73 }
其他脚本(诸如UI1..UI4、UIBase)就不贴了,都没什么,在SceneA->SceneB->SceneC都是用Application.LoadLevel(),而在Scene X -> SceneA之前,就会调用LaunchGame.cs中的函数DestroyAllUIGameObject(),然后才LoadLevel(场景A)。