NGUI 多场景情况下 管理多个界面
简单的说就是在一个AllUI场景中,所有场景所需要的界面都挂在一个Empty GameObject下,然后这个Empty GameObject在代码中DontDestroyOnLoad,但是回到这个AllUI场景时根据实际情况决定要不要Destroy掉!具体如下:
因为我们的游戏场景分布是这样的情况:
注册/登陆界面 所在的场景A,游戏场景B、世界场景C、战斗场景D。
为了便于界面的管理(比如,你打开界面1->界面2->界面3,然后又跳转来跳转去的,这个时候如果将所有界面继承一个基类UIBase,然后保存在一个字典里,显示一个全屏界面就可以用一个for循环解决);
主要的做法就是:将所有的界面都放在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:
using UnityEngine;
public class LaunchGame : MonoBehaviour
{
public GameObject mAllUIGameObject = null;
private static LaunchGame mInstance = null;
public static LaunchGame Instance
{
get
{
return mInstance;
}
private set
{
}
}
void Start ()
{
if (mInstance == null)
{
Output.Log("LaunchGame.Start(), mInstance == null");
mInstance = this;
}
DontDestroyOnLoad(mAllUIGameObject);
UIManager.Instance.Init();
Output.Log("LaunchGame.Start()");
}
void Update ()
{
}
public void DestroyAllUIGameObject()
{
Destroy(mAllUIGameObject);
}
}
UIManager.cs:
using System.Collections.Generic;
// 面板类型
public enum UIType
{
UI1,
UI2,
UI3,
UI4,
}
// 界面逻辑管理器
public class UIManager : Singleton<UIManager>
{
public UI1 ui1 = null;
public UI2 ui2 = null;
public UI3 ui3 = null;
public UI4 ui4 = null;
Dictionary<UIType, UIBase> mUIDic = new Dictionary<UIType, UIBase>();
// 初始化界面逻辑
public void Init()
{
CheckMembers();
InitAllPanel();
}
// 检测成员变量是否有效
void CheckMembers()
{
Assert.IsNotNull(ui1, "UIManager.CheckMembers(), ui1 is null object!");
Assert.IsNotNull(ui2, "UIManager.CheckMembers(), ui2 is null object!");
Assert.IsNotNull(ui3, "UIManager.CheckMembers(), ui3 is null object!");
Assert.IsNotNull(ui4, "UIManager.CheckMembers(), ui4 is null object!");
}
// 初始化所有面板
void InitAllPanel()
{
mUIDic.Add(UIType.UI1, ui1);
mUIDic.Add(UIType.UI2, ui2);
mUIDic.Add(UIType.UI3, ui3);
mUIDic.Add(UIType.UI4, ui4);
foreach (UIBase ui in mUIDic.Values)
{
if (ui.m_panel != null)
{
ui.CheckWidget();
ui.Init();
ui.BindingEvent();
ui.Reset();
}
}
}
// 显示指定面板
public void ShowPanel(UIType type)
{
foreach (KeyValuePair<UIType, UIBase> item in mUIDic)
{
if (type == item.Key)
{
item.Value.Show();
}
else
{
item.Value.Hide();
}
}
}
}
其他脚本(诸如UI1..UI4、UIBase)就不贴了,都没什么,在SceneA->SceneB->SceneC都是用Application.LoadLevel(),而在Scene X -> SceneA之前,就会调用LaunchGame.cs中的函数DestroyAllUIGameObject(),然后才LoadLevel(场景A)。
以上就是大致思路及实现,如果存在不好的方面,麻烦告知,不胜感激!
update:2014.11.29
之后在实现过程中,发现上述思路存在问题,修改如下:UI统一放在LoginScene场景中,游戏启动的时候会先加载一个LaunchGameScene场景,其中脚本负责做的事情就是使游戏中使用单体对象不释放,主要就是使用DontDestroyOnLoad函数,然后才跳转到LoginScene进行登录流程,之后才进入GameScene。然后注销账号回到登录界面的时候只是切换到LoginScene场景中,而没有切换到LaunchGameScene场景!具体流程如下:

如果有更多的场景,同理一样!
此思路如果存在什么问题,麻烦指教,谢谢!!
NGUI 多场景情况下 管理多个界面的更多相关文章
- Linux的虚拟内存管理-如何分配和释放内存,以提高服务器在高并发情况下的性能,从而降低了系统的负载
Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...
- Vue 不使用Vuex的情况下进行状态管理
在封装自己的Vue ui库的时候,往往要封装一些比较复杂的组件,比如说table,form之类.这些组件由于功能繁杂,还涉及到子组件嵌套及通信,如果没有一套状态管理方案的话很容易导致代码难以阅读.难以 ...
- [daily][archlinux][fonts] 在linux下管理字体
序: linux是社区搞出来, 商业应用也都是服务器场景.社区里又都是技术人员.字体又是细节.而且会英文早成了标配.所以没有很多社区以外的人力来搞字体这个毫无回报的东西. 结果很自然的,装linux桌 ...
- 数据库表设计时一对一关系存在的必要性 数据库一对一、一对多、多对多设计 面试逻辑题3.31 sql server 查询某个表被哪些存储过程调用 DataTable根据字段去重 .Net Core Cors中间件解析 分析MySQL中哪些情况下数据库索引会失效
数据库表设计时一对一关系存在的必要性 2017年07月24日 10:01:07 阅读数:694 在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表中不就可以了吗?真是说,网上信息什么都 ...
- @Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码
一.前言 这篇算是类加载器的实战第五篇,前面几篇在这里,后续会持续写这方面的一些东西. 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证) 还是Tomcat,关于类加载器的趣味实验 ...
- 【DATAGUARD】物理dg在主库丢失归档文件的情况下的恢复(七)
[DATAGUARD]物理dg在主库丢失归档文件的情况下的恢复(七) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到 ...
- Spring @Transactional注解在什么情况下会失效,为什么?
出处: https://www.cnblogs.com/hunrry/p/9183209.html https://www.cnblogs.com/protected/p/6652188.htm ...
- Springboot在有锁的情况下如何正确使用事务
1. 概述 老话说的好:想要赚钱,就去看看有钱人有什么需求,因为有钱人钱多,所以赚的多. 言归正传,在Java项目的研发中,"锁"这个词并不陌生,最经典的使用场景是商品的超卖问题. ...
- 喜提JDK的BUG一枚!多线程的情况下请谨慎使用这个类的stream遍历。
你好呀,我是歪歪. 前段时间在 RocketMQ 的 ISSUE 里面冲浪的时候,看到一个 pr,虽说是在 RocketMQ 的地盘上发现的,但是这个玩意吧,其实和 RocketMQ 没有任何关系. ...
随机推荐
- SNMP开发c#,高薪诚聘,或者外包开发
现在手里有一个IT资产管理方面的项目,主要会用到SNMP协议,要用这个协议进行开发,对网络上的设备进行控制, 现在高薪诚聘高手,或者项目外包合作,有意向的同学们可以联系我,时间紧迫, QQ:39011 ...
- Effective c++
static 声明在堆上申请静态存储 对于局部变量,将存储方式改为静态存储 对于全局变量,将连接方式局限在文件内 类中static变量:属于整个类,独立存储,没有this指针 inline inlin ...
- IO操作概念。同步、异步、阻塞、非阻塞
“一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作. 同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO. 阻塞IO和非阻塞IO的区别在于第 ...
- webstorm安装后的一些设置技巧:
如何更改主题(字体&配色):File -> settings -> Editor -> colors&fonts -> scheme name.主题下载地址 如 ...
- FusionCharts中仪表盘相关属性
上上周用FusionCharts做了几个报表,里面有个仪表盘,当时查属性查疯了,现在把相关的一些属性记下来,方便以后查找. -------------------------仪表盘重要属性解析---- ...
- jenkins调度selenium脚本不打开浏览器解决办法
原文地址: http://blog.csdn.net/achang21/article/details/45096003 The web browser doesn't show while run ...
- HDOJ(2438)几何里的三分
Turn the corner http://acm.hdu.edu.cn/showproblem.php?pid=2438 题目:一辆车能否在一个路口拐弯,看图就很明白啦. 算法:见下图,只要求出图 ...
- Zepto API 学习
1. after, before, append, prepend 的区别 A.after(B) ==== B.insertAfter(A) // B 放在 A 的后面 A.before(B) == ...
- Android Studio tips1
Android Studio 真机测试出现 device can not found 1.安装与手机版本一样的sdk 2.(重要!!)手机的驱动在电脑上没有正确的安装,安装豌豆荚可以解决!
- 已解决: 已引发: "无法加载 DLL“opencv_core2410”: 找不到指定的模块。
之前是win7 32位系统,程序运行没有问题:换了64位 win7后,系统就找不到opencv相关库了,网上各种查询解决方法,感觉不太可行,或者很麻烦...多次试验后,找到方便关键的解决方案如下: 计 ...