之前刚来现在这个项目的时候,我就跟我们的主程提过使用FGUI去替代UGUI的事情。 原因有以下:
我记得我在和我们Leader在讨论这个问题的时候,我给他讲了一些FGUI的好处, 很明显,他很也意动, 但是因为他可能需要考虑很多其它的问题, 所以也不敢下决定, 所以让我给他演示一下FGUI的一些简单的用法与操作, 做一个UGUI的ScrollRectList无限滚动列表。 很可惜,我自己在尝试使用FGUI并没有专门去研究这个, 我只是看过FGUI的UnitySDK的源码, 觉得代码不错,而且扩展方便, 在使用上至少是一个可控级别的。 所以我没有办法给他简单的展示这个例子, 我告诉他FGUI的例子中有, 但是我估计他是觉得连我都不知道怎么去用,就向他热情的安利, 本来就摇摆的心, 直接就给出了拒绝的答复。 之后项目就开始大量进人手, 在之后就开始使用uGUI进行大量的开发,想要调整,也需要很长的时间,所以也就搁置了这个提议。
其实我个人在他拒绝这个提议的时候,是很伤感的。 为什么呢? 因为在我加入到这个团队的时候, 团队属于初创, 当时才3个人。而且UI的东西完全就没有动起来。 我觉得完全可以拿出一周左右的时间,或者派专人, 或者他自己亲自去调研,体验一下这个东西的利弊, 然后再做决定。 谈起这个,说说我成都的老东家, 当时属于第一次使用Unity做游戏, 也是一个初创团队,我也很有幸再立项之前就加入到了团队中。 也是我在项目中提议使用 当时特别新的技术 ulua 做游戏开发以及基础框架, 同时做热更新。我记得那个时候是14年, 当我提出来之后, CTO,主程还有我们大家都亲自去试验了一把, 最后大家一致决定采用(原来的公司有PC开发背景,使用lua特别多)。 在这里给我们点个赞。 对比起来,现在的项目Leader不够果断。虽然可能有一些客观原因。我个人也是很理解,但是我还是希望这个东西能融进项目中来, 因为这个融入进来之后有一个很大的作用。
最后再说说我自己在搭建自己的框架的时候使用FGUI进行开发的时候,遇到的一些小小困扰:
基于以上的3个种整体适配方式,就可以做我们的ugui的适配。 我们先只好整体适配方式, 然后对于一些比较普通的UI元素, 是不需要关心适配的详细情况的, 对于需要匹配全屏的界面我们只需要设置为随着屏幕扩展就可以了。然后需要处理的是一些特殊情况只有, 需要固定位置的UI元素, 比如我有一个聊天界面, 这个聊天界面是永远固定在屏幕坐下角的, 这个时候就需要使用UGUI提供的锚点的方式处理, 将这个UI元素锚在右下角。 (如果对这个不太理解,估计你还需要再研究一段UI制作和写一段时间的UI)
这应该就是UGUI的最简单的适配方式。
下面我们再来看FGUI的适配, FGUI的适配与UGUI的大同小异的。FGUI提供一个组件名为: UI Content Scaler
图中: Scale Mode 表示你的整体适配方式: 提供选项与Unity的组件差不太多,一般我们选择 Scale With Screen Size , 采用缩放屏幕的方式进行整体适配. Design Resolution 为项目的设计分辨率,会以为基准做缩放处理, Screen Math Mode 为缩放基准选择: 1. 以高度或者宽度适配 2. 以宽度适配 3. 以高度适配。 FGUI没有提供相比于Unity那么完善的配置, 但是这些已经足够我们做适配了。 一般情况下我们都选以高度或者宽度适配来进行适配。
同样的,对于普通的UI元素我们不用考虑适配的问题。 我们只需考虑需要规定位置的UI元素和全屏的UI元素。
这个时候请允许我直接引用官网上面的内容,用于描述我们要做的适配的问题:
全屏界面适配
全局缩放后,大部分UI都不需要做任何调整,只有一个例外,就是设计为全屏的界面。在上例中,在设计分辨率下,全屏界面的大小是960x640,我们也是按这个大小设计全屏组件的。全局缩放后,这时逻辑屏幕的大小变成1138x640了,那大小就不一致了。这是我们需要重新调整组件大小使之满屏,即
//设置组件全屏,即大小和逻辑屏幕大小一致。
//组件的内部应该做好关联处理, 以应对大小改变。
aComponent.SetSize(GRoot.inst.width, GRoot.inst.height);
//或者更简洁的方式
aComponnet.MakeFullScreen();
当然,这仅仅是处理全屏界面的一种方式。在有的情况下,例如如果选用“MatchHeight”模式,也就是高度优先的适配方法,这种方法保证了UI界面垂直方向的内容总是铺满,而水平方向就有可能超出屏幕。这种适配方式需要设计师有“安全区域”的设计思维,不能安排内容在超出屏幕的部分。例如,将全屏界面居中,牺牲掉两边的内容:
aComponent.x = (GRoot.inst.width – aComponent.width)/2;
这样,左边缘和右边缘将会被屏幕边缘裁剪掉,这要求设计师在设计时就考虑到这种情况。
自动调整UI布局
全屏组件在适配过程中需要重新设置全屏,那么组件大小就会发生变化,这时需要使用关联系统让组件内的元素自动布局在正确的位置。实例可以参考关联系统。
全屏界面适配
全局缩放后,大部分UI都不需要做任何调整,只有一个例外,就是设计为全屏的界面。在上例中,在设计分辨率下,全屏界面的大小是960x640,我们也是按这个大小设计全屏组件的。全局缩放后,这时逻辑屏幕的大小变成1138x640了,那大小就不一致了。这是我们需要重新调整组件大小使之满屏,即
//设置组件全屏,即大小和逻辑屏幕大小一致。
//组件的内部应该做好关联处理, 以应对大小改变。
aComponent.SetSize(GRoot.inst.width, GRoot.inst.height);
//或者更简洁的方式
aComponnet.MakeFullScreen();
当然,这仅仅是处理全屏界面的一种方式。在有的情况下,例如如果选用“MatchHeight”模式,也就是高度优先的适配方法,这种方法保证了UI界面垂直方向的内容总是铺满,而水平方向就有可能超出屏幕。这种适配方式需要设计师有“安全区域”的设计思维,不能安排内容在超出屏幕的部分。例如,将全屏界面居中,牺牲掉两边的内容:
aComponent.x = (GRoot.inst.width – aComponent.width)/2;
这样,左边缘和右边缘将会被屏幕边缘裁剪掉,这要求设计师在设计时就考虑到这种情况。
自动调整UI布局
全屏组件在适配过程中需要重新设置全屏,那么组件大小就会发生变化,这时需要使用关联系统让组件内的元素自动布局在正确的位置。实例可以参考关联系统。
所以对于FGUI来说, 使用自己设置全局界面 来替代Unity的自扩张的UI锚点设计, 使用关联系统来替代UGUI的锚点定位功能。
但是再我实际的使用中, 我发现官网的方法在使用有一些困扰。 比如我当前的运行分辨率是跟之前一样是2280x1242, 根据官网的方式去设置, 我会把我需要设置的组件的大小设置成为 2280x1242。 这我想象的不太一样, 我需要的应该是类似Unity的Expand模式下的那种, 以设计的分辨率为基准,经过一点扩张或者缩小正好满足铺满整个屏幕的的分辨率。 因为假如我们底图不是九宫格类型的话, 当进行这样设置之后, 如果设计分辨率和运行分辨率相差太大的话,会导致大量内容看不到, 所以我应该计算当前屏幕经过整体缩放之后的分辨率。然后将我们的全屏界面设置为当前分辨率。
function UIMgr.InitSize()
UIMgr.DesignWidth = 1334
UIMgr.DesiginHeight = 750
scale = math.max(UIMgr.DesiginHeight / GRoot.inst.height, UIMgr.DesignWidth / GRoot.inst.width)
UIMgr.width = GRoot.inst.width * scale + 2
UIMgr.height = GRoot.inst.height * scale + 2
end
大致代码就在上面了, 我们通过这样计算出当前屏幕的分辨率,然后设置给需要表示为全屏的界面,为什么要+2的原因,是因为这里计算出来数值是个浮点数,会不精确,可能会导致界面出现很小黑边。
function BaseView:MaskBgFull()
self:MaskAsFull("full_bg")
end
function BaseView:MaskAsFull( name )
local aObject = self.m_goView:GetChild(name)
if aObject then
aObject:SetSize(UIMgr.width, UIMgr.height)
aObject:SetPosition(0,0,0)
end
end
上面是我们调用的代码, 在基类封装一个方法, 如果有需要设置为全屏幕的UI元素就调用这个方法, 同时约定好如果有需要设置为全屏幕的背景, 那么在制作UI的时候就设置名字为: full_bg。这个方法会在初始化的时候进行调用。
以上就是我理解的UGUI的适配方法 和 FGUI的适配方法。
诸君共勉。