文档章节

简易 Unity3D UI 框架

ylme
 ylme
发布于 2017/05/19 16:33
字数 2296
阅读 145
收藏 1
点赞 0
评论 0

看见一篇介绍 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
博文 39
码字总数 40752
作品 0
广州
程序员
如何把UGUI当做一个插件使用(删除Unity中的UGUI,导入UGUI源码进入项目)

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

qq826364410 ⋅ 05/09 ⋅ 0

Unity3D - 图片资源导入的一些基础知识

在上一篇文章里 Unity3D - 你导入的资源,并不是Unity使用的资源 介绍过,Unity使用的资源是你无法直接操作的,那么对于图片资源,我们应该如何去处理和优化工作流程呢? 图片资源的分类 在U...

qq_17758883 ⋅ 04/11 ⋅ 0

刘国柱- Unity游戏开发深度学习 系列课程福利大放送

刘国柱--Unity游戏开发深度学习 系列课程福利大发送!不单优惠, 还送Unity最新版本必备实战书籍! HI, 各位热心的Unity爱好者与学员,《Unity3D/2D 游戏开发从0到1(第二版)》书籍已经正式发...

Liu_guozhu ⋅ 05/23 ⋅ 0

Unite Beijing 2018|行业应用精彩议题曝光

我们不久之前为大家提前曝光了部分大会精彩技术议题,引起了大家的广泛关注。作为世界顶尖的内容创作引擎,Unity不仅仅可用于跨平台的游戏开发,越来越多的开发者将Unity运用到制造业,汽车,...

weixin_41849687 ⋅ 04/20 ⋅ 0

Unite Beijing 2018 | 技术专场部分精彩议题曝光

离5月11-13日的Unite Beijing 2018的开幕仅剩一个半月了,届时来自全球的Unity技术达人,行业精英和全球合作伙伴将为你带来史无前例的80余场技术演讲,内容涵盖Unity跨平台内容开发经验,标杆...

weixin_41849687 ⋅ 04/20 ⋅ 0

Rider 2018.1 发布,.NET 跨平台集成开发环境

Rider 2018.1 发布,新版本增加了许多新功能,改进和修复。 更新内容: Roslyn analyzers: in addition to Rider’s own 2400 code inspections to help you detect errors and code smells......

周其 ⋅ 04/20 ⋅ 0

学习Mono与Unity3D关系的笔记

Xamarin公司开发的跨平台 .NET运行环境,是.NET框架的另一种实现。区别在于,它可以跨平台。(Unity的跨平台特性依赖于Mono) Mono的组成。 1.C#编译器。 最新的Momo版本(5.0+)c#编译器完全...

lishengxu159 ⋅ 05/05 ⋅ 0

白鹭引擎 5.3.0 正式发布,支持 3D 游戏开发

一直关注白鹭引擎的童靴会发现,今天白鹭引擎先后完成了白鹭引擎5.2.0、白鹭引擎5.3.0两个版本的更迭,在周三发布《白鹭引擎稳定版即将发布,后续路线图同步公开》文中,我们已详细介绍了白鹭...

白鹭科技 ⋅ 05/25 ⋅ 0

Unity3D 单片草顶点摆动

Shader "MobileShadow/Grass" { Properties { MainTex ("MainTex", 2D) = "white" {} AlphaR ("AlphaR", 2D) = "white" {} Settings ("Settings", Vector) = (1.5,0.1,0.5,0) } SubShader { ......

yuyingwin ⋅ 05/09 ⋅ 0

Unity2018新功能抢鲜 | Package Manager

本文首发于“洪流学堂”微信公众号。 洪流学堂,让你学Unity快人几步 一个包是一个容器,它可以包含各种资源的组合:shader、纹理、插件、图标、脚本等,可以增强项目的各个部分。相对于Ass...

zhenghongzhi6 ⋅ 04/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 42分钟前 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 50分钟前 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 56分钟前 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

容器之查看minikue的environment——minikube的环境信息

执行如下命令 mjduan@mjduandeMacBook-Pro:~/Docker % minikube docker-envexport DOCKER_TLS_VERIFY="1"export DOCKER_HOST="tcp://192.168.99.100:2376"export DOCKER_CERT_PATH="/U......

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

mysql远程连接不上

设置了root所有hosts远程登录,可是远程登录还是失败,原因可能如下: 登录本地数据库 mysql -uroot -p123456 查询用户表 mysql> select user,host,password from mysql.user; 删除密码为空的...

冰公子 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部