文档章节

简易 Unity3D UI 框架

ylme
 ylme
发布于 2017/05/19 16:33
字数 2296
阅读 152
收藏 1

看见一篇介绍 Unity3D UI 框架编写的文章,并且给出了示例代码。然后去了解了一下。讲道理,示例代码蛮乱的,不知道有一些是不是直接从项目代码拷贝然后简单修改,对于一个简单的框架来说,有很多不必要的混乱逻辑。而且我又喜欢粉色,所以就重新编写了,话不多说先上运行图示。具体代码点这里

运行图示

想了解更多信息具体查看代码。这篇博客主要谈一谈 UI 框架基本的需求。UI 框架有很多实现方式,比如多个界面共用一个摄像机渲染还是单个界面单个摄像机渲染,但是基本的需求是一致的。掌握了基本的需求,才能适应不同项目策划百变的需求。最后需求分析基于手游,界面基于 NGUI

基本情景

UIOper

游戏玩法一般分为 UI 玩法和核心玩法。假设核心玩法是战斗。UI 玩法与核心相互交织连接,比如打开装备界面锻炼装备,这样战斗时就更厉害,还比如打开聊天界面与好友聊天,一起组队打 Boss 。上图是常见的操作之一,总结为两句话:界面之间跳转,界面与战斗跳转,这是最基本的需求情景。

了解了基本情景后来探索更多的细节吧。

界面渲染

渲染是最现实的问题,毕竟界面要先能被看见。新创建一个 Camera 独立负责界面渲染,和主场景和战斗场景渲染独立开来。对于这个只渲染 UI 的 Camera 设置 Camera.cullingMask 指定渲染的 Layer,避免冗余渲染,同样界面(GameObject)的 Layer 也要设置为值才能被显示 。这样当调节战斗场景和主场景摄像机渲染时,UI 不会受到影响,相应的修改 UI Camera 的选项时,也不会影响非 UI 的渲染。

界面跳转与界面层级(depth,深度值)

界面跳转与界面层级是相互关联的。比如某个导航按钮打开一个新的界面,但新的界面层级比较低,这样在重叠区域导航按钮就会遮挡新打开的界面,这不符合实际需求,因此需要合理的管理界面层级,防止出现错误的遮挡。界面跳转涉及多个界面,界面层级涉及到渲染次序进而影响显示顺序,NGUI 中可以用 depth 控制渲染次序,UGUI 又是另一种方式控制渲染次序,这里使用 NGUI 深度值进行描述,目的都是一样的,就是控制渲染秩序。

当游戏界面足够的简单,UI 管理就更简单。如下所示。比如仅仅创建两个 UIPanel,ToolPanel 深度值更大,显示优先级更高,PlayPanel 优先级低一些,用来展示玩法,由于游戏界面很简单,此时完全可以把所有界面都创建好,如 UI1 和 UI2 。比如需要显示 UI2 时,设置 UI1 为 Inactive 然后设置 UI2 为 Active 。通过这种方式,你就可以完成一个超简单的 UI 框架,当然它的功能备受限制,但是对于简单的小游戏来说,也足够了。

UIRoot
	PlayPanel
		UI1
		UI2
	ToolPanel
		Tool

然而很多时候游戏会涉及很多界面。这样就得考虑更灵活的实现方式。

  • 缩放选择。NGUI 使用 UIRoot 组件进行缩放。因此完全可以所有界面共用一个 UIRoot 组件。如下格式。Panel1 到 Panel3 是三个不同的界面。
UIRoot
	Panel1
        Panel2
        Panel3

当然若不在乎冗余的 UIRoot 组件,或者想个别界面采用特俗的缩放方式,也可以每个节目单独一个 UIRoot 组件。如下。

UIRoot1
	Panel
UIRoot2
       Panel
UIRoot3
       Panel
  • 摄像机选择。再提一下,摄像机指定 Layer 且 UI 界面 GameObject 的 Layer 设置为值。
  • 每个界面单独一个摄像机。设置界面所在摄像机的 Camera.depth 即可设置界面层级。这种方式需要避免摄像机错乱,例如界面 A 的摄像机又渲染了界面 B 。有一种解决方法是设置 UIRoot 的位置,避免不同界面出现重叠。
  • 所有界面共用单个摄像机。修改界面层级通过设置 UIPanel.depth 。这种方式设置界面层级时需要设置该界面所有 UIPanel.depth 。比如设置 depth 是 1000,则需要排序该界面所有 UIPanel 然后从小到大分别设置为 1000 、1001 、1002 等。
  • 界面类型。游戏中存在不同类型的界面,有些界面就应该具有更高的优先级,遮挡住其他界面,例如导航界面。还有一种常见的就是玩法的界面,不同的玩法界面相对独立。比如当界面 A 与界面 B 交互时,此时采用窗口跳转即可。
  • 界面跳转。打开新界面时,是否禁用其他渲染。关闭新界面时,恢复之前的渲染状态
  • 禁用其他渲染(包括禁用主场景渲染)。打开全屏窗口时可以采用此方式。此时设置新界面层级,可以直接设置深度值。
  • 不禁用其他渲染。打开非全屏窗口时可以采用此方式。此时设置新界面层级,需要动态计算深度值(可以递增深度值)并设置到界面,使新界面可以遮挡其他相应界面显示。
  • 界面深度值管理。NGUI 采用深度值。UGUI 是另外一种方式。总之目的是实现合理的界面遮挡。
  • 界面与战斗。进入战斗后,一般之前的那些玩法界面都需要被隐藏,取而代之的是用于战斗中的界面。退出战斗后关闭战斗中的界面,然后再恢复进入战斗前的玩法界面状态。当然了进入战斗后如果退出了未显示场景,此时可以停止主场景的渲染。
  • 界面与消息屏蔽。比如界面 A 显示在界面 B 的上方,一般情况下肯定都不想在界面 A 上随便点击,却触发了界面 B 上的事件,对吧。因此这一项也是需要考虑的。

这些都是基本的 UI 框架需求。这些需求可以根据项目情况或简单或复杂实现。相信读到这里,你内心也有了一些自己的想法了,是吧。

再进一步,资源,内存,效率

  • 界面资源。实际项目中很多界面,不可能全部载入到内存,因此都是用到时才加载。若所有界面被单一个摄像机渲染,资源文件就不用包含摄像机,只需包含相应的面板即可。
  • 资源可被保存到 .unity 文件。使用时加载 .unity 文件。
  • 资源也可被保存到 prefab 文件中。
  • 界面内存。若界面不多,使用的界面就一直存放在内存中。若需要考虑性能,则要处理资源销毁从而腾出内存空间。
  • 效率问题。若界面很大且包含了更多的内容,打开界面时若全部加载所有内容,会导致界面打开比较慢。此时就可以考虑界面拆分。先载入必须显示的内容,剩下的内容根据需要动态加载。这一步可以单个界面自己负责实现,也可以考虑到整合到框架中,方便使用的开发者。

开发

到这一步一个框架就开发出来使用了。在实际项目需求中可能会为了便利性,进一步增加一些通用功能。下面列举一些项目中会实际处理的事情。

  • 打开界面时,传递参数。
  • 打开和关闭界面时,播放动画。
  • 界面的刷新,包括玩法上的主动刷新(如获取新的道具刷新背包)或者断线重连后的刷新。
  • 界面的重复打开。
  • 界面显示特效。
  • 界面显示模型。

下面是前面提到的我重新实现的小框架的例子。例子很简单,就是显示一个界面。在 Awake 中进行初始化处理即可。之后便可以调用 WndMgr.inst.ShowWindow(WndId.shop); 来显示界面。

using UnityEngine;
using TinyWnd;

public class ShopWnd : Wnd
{
    protected override void OnAwake()
    {
        _wndId = WndId.shop;
        _colliderMode = WndColliderMode.transparent;
        _closeClickBg = true;
        _unifiedClose = true;
    }
}

提一点,组件中 AwakeStart 执行顺序,大家都知道。要注意的地方是 AwakeStart 不一定是在同一帧执行。当调用 AddComponent 添加新的组件时,初始化完毕后 Awake 会被调用,而 Start 未被调用。因此组件的一些初始化处理放在 Awake 函数中会更加合适。这样的话,动态添加这个组件后就可以使用了,而不用担心一些初始化操作未被执行。


我的博客地址 https://my.oschina.net/iirecord/blog

© 著作权归作者所有

共有 人打赏支持
ylme
粉丝 10
博文 40
码字总数 41754
作品 0
广州
程序员
Mogoson/CubemapRenderer

CubemapRenderer English Manual 概述 Unity Cubemap渲染器。 需求 有时,发现一些Unity资源包中的场景的环境效果不错,希望将其渲染成Cubemap供天空盒使用。 Unity场景中需要制作一些反射效...

Mogoson
08/22
0
0
如何把UGUI当做一个插件使用(删除Unity中的UGUI,导入UGUI源码进入项目)

最近闲着没事,一直也都知道UGUI是开源的,所以就想着把UGUI的源代码放到Unity里面,看一看能不能用,经过一番调试,终于弄好了,有兴趣的同学可以看一下,欢迎交流沟通。 欲练神功,必先自宫...

qq826364410
05/09
0
0
Unity 3D与Android Studio安卓交互之-导出jar包

u3d与安卓 jar 包交互 Chinar 教程效果: import android.support.v7.app.AppCompatActivity;import android.os.Bundle; import com.unity3d.player.UnityPlayer;import com.unity3d.player.......

chinar-yunxi
04/12
0
0
Android Studio安卓导出aar包与Unity 3D交互

Unity与安卓aar 包交互 Chinar 教程效果: import android.support.v7.app.AppCompatActivity;import android.os.Bundle; import com.unity3d.player.UnityPlayer;import com.unity3d.playe......

chinar-yunxi
04/19
0
0
Unity3D插件详细评测及教学下载

引言:想用Unity3D制作优秀的游戏,插件是必不可少的。工欲善其事必先利其器。本文主旨是告诉使用Unity3D引擎的同学们如何根据需求选择适当的工具。为此我写了插件的经验及理论讲解,涉及插件...

郑华勇
2012/12/14
0
1

没有更多内容

加载失败,请刷新页面

加载更多

20180920 rzsz传输文件、用户和用户组相关配置文件与管理

利用rz、sz实现Linux与Windows互传文件 [root@centos01 ~]# yum install -y lrzsz # 安装工具sz test.txt # 弹出对话框,传递到选择的路径下rz # 回车后,会从对话框中选择对应的文件传递...

野雪球
今天
2
0
OSChina 周四乱弹 —— 毒蛇当辣条

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 达尔文:分享花澤香菜/前野智昭/小野大輔/井上喜久子的单曲《ミッション! 健?康?第?イチ》 《ミッション! 健?康?第?イチ》- 花澤香菜/前野智...

小小编辑
今天
7
3
java -jar运行内存设置

java -Xms64m #JVM启动时的初始堆大小 -Xmx128m #最大堆大小 -Xmn64m #年轻代的大小,其余的空间是老年代 -XX:MaxMetaspaceSize=128m # -XX:CompressedClassSpaceSize=6...

李玉长
今天
4
0
Spring | 手把手教你SSM最优雅的整合方式

HEY 本节主要内容为:基于Spring从0到1搭建一个web工程,适合初学者,Java初级开发者。欢迎与我交流。 MODULE 新建一个Maven工程。 不论你是什么工具,选这个就可以了,然后next,直至finis...

冯文议
今天
2
0
RxJS的另外四种实现方式(四)——性能最高的库(续)

接上一篇RxJS的另外四种实现方式(三)——性能最高的库 上一篇文章我展示了这个最高性能库的实现方法。下面我介绍一下这个性能提升的秘密。 首先,为了弄清楚Most库究竟为何如此快,我必须借...

一个灰
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部