简单的说就是在一个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 多场景情况下 管理多个界面的更多相关文章

  1. Linux的虚拟内存管理-如何分配和释放内存,以提高服务器在高并发情况下的性能,从而降低了系统的负载

    Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...

  2. Vue 不使用Vuex的情况下进行状态管理

    在封装自己的Vue ui库的时候,往往要封装一些比较复杂的组件,比如说table,form之类.这些组件由于功能繁杂,还涉及到子组件嵌套及通信,如果没有一套状态管理方案的话很容易导致代码难以阅读.难以 ...

  3. [daily][archlinux][fonts] 在linux下管理字体

    序: linux是社区搞出来, 商业应用也都是服务器场景.社区里又都是技术人员.字体又是细节.而且会英文早成了标配.所以没有很多社区以外的人力来搞字体这个毫无回报的东西. 结果很自然的,装linux桌 ...

  4. 数据库表设计时一对一关系存在的必要性 数据库一对一、一对多、多对多设计 面试逻辑题3.31 sql server 查询某个表被哪些存储过程调用 DataTable根据字段去重 .Net Core Cors中间件解析 分析MySQL中哪些情况下数据库索引会失效

    数据库表设计时一对一关系存在的必要性 2017年07月24日 10:01:07 阅读数:694 在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表中不就可以了吗?真是说,网上信息什么都 ...

  5. @Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码

    一.前言 这篇算是类加载器的实战第五篇,前面几篇在这里,后续会持续写这方面的一些东西. 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证) 还是Tomcat,关于类加载器的趣味实验 ...

  6. 【DATAGUARD】物理dg在主库丢失归档文件的情况下的恢复(七)

    [DATAGUARD]物理dg在主库丢失归档文件的情况下的恢复(七) 一.1  BLOG文档结构图 一.2  前言部分 一.2.1  导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到 ...

  7. Spring @Transactional注解在什么情况下会失效,为什么?

    出处:  https://www.cnblogs.com/hunrry/p/9183209.html   https://www.cnblogs.com/protected/p/6652188.htm ...

  8. Springboot在有锁的情况下如何正确使用事务

    1. 概述 老话说的好:想要赚钱,就去看看有钱人有什么需求,因为有钱人钱多,所以赚的多. 言归正传,在Java项目的研发中,"锁"这个词并不陌生,最经典的使用场景是商品的超卖问题. ...

  9. 喜提JDK的BUG一枚!多线程的情况下请谨慎使用这个类的stream遍历。

    你好呀,我是歪歪. 前段时间在 RocketMQ 的 ISSUE 里面冲浪的时候,看到一个 pr,虽说是在 RocketMQ 的地盘上发现的,但是这个玩意吧,其实和 RocketMQ 没有任何关系. ...

随机推荐

  1. Action向前台输出

    import java.io.IOException;import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse ...

  2. FlASK中的endpoint问题

    先贴一点有关的flask代码,时间有限,我慢慢扩充 以下是flask源码中app.py中add_url_rule的代码. 主要是view_func  -- endpoint -- url 之间的对应关 ...

  3. ReactJS学习笔记(三)

    需要注意的问题: 1.组件名称开头字母一定要大写.(PS:原因是 React 的 JSX 里约定分别使用首字母大.小写来区分本地组件的类和 HTML 标签.) 2.this.props.childre ...

  4. NHibernate系列文章二十三:NHibernate查询之Criteria查询(附程序下载)

    摘要 上一篇文章介绍了NHibernate HQL,他的缺点是不能够在编译时发现问题.如果数据库表结构有改动引起了实体关系映射的类有改动,要同时修改这些HQL字符串.这篇文章介绍NHibernate面 ...

  5. 重置zend studio 默认设置的方法

    转载自:http://www.zendstudio.net/archives/reset-the-zend-studio-settings/ 这个方法类似于手机的"恢复出厂设置"的 ...

  6. Java是目前最广泛的_______编程语言

    计算机网络 注意:在配置环境变量时,classpath是为找文件服务的

  7. 答:SQLServer DBA 三十问之三:有哪些操作会使用到TempDB;如果TempDB异常变大,可能的原因是什么,该如何处理

    3. 有哪些操作会使用到TempDB:如果TempDB异常变大,可能的原因是什么,该如何处理: tempdb的用途:1)存储专用和全局临时变量,不考虑数据库上下文: 2)与Order by 子句,游标 ...

  8. requirejs的使用

    requirejs的优点: 1.防止在js的加载过程中,阻止页面的渲染: 2.可以引入多个js文件: 3.可以写出重复使用的js模块: 4.有效的防止命名的冲突,通过将变量分装在模块中的方式实现: r ...

  9. KBMMW 4.92.00 发布

    We are happy to announce the release of kbmMW Professional and Enterprise Edition. Yet again kbmMW c ...

  10. XMl.02-约束

    DTD约束 DTD的书写位置 XML构建模块 DTD定义元素 DTD属性的定义 DTD实体的定义 schema约束 命名空间 schema约束的书写流程 XML被设计为一种很灵活的标记文档. 但是,有 ...