UI初学第二课
Case2
这次做的案例跟Case1是有关联的,既然Case1做了Game中的HUD上的UI,那么这次Case我就做个主菜单的UI。
逻辑思路:首先菜单上要有Play Game,Quit Game,这是最基础的,或者也可以加一些选项,例如选择角色,或者视频分辨率等等。这里做个简单案例就用一个选择视频分辨率来做吧。明确了需要的东西,那么实现的逻辑是什么呢?我需要点击PlayGame就进入Case1已经设置好了的Game,这里就不能忽视Unreal中的Level概念了,Case1是一个Level,如果我要从菜单中跳转到Case1中的Level那么我就不能再要跳转的Level中去设置我的菜单,所以我要新建一个Level去存储我的菜单,实现的事件就是点击PlayGame的Button通过节点open level进入Game.同理Quit Game也可以通过Quit Game的节点去退出。(还有一个方法就是利用向Execute Consle Command(控制台的命令)输入命令)。
首先,新建一个Level,接下来就与Case1中的方法差不多实现自己想要的UI画面,我这里只强调一些新的内容。
将图片背景导入,找到image这个控件添加到Canvas Panel上作为背景,自行将image调整到布满整个Panel,这里注意不要忘记了Anchors,每种不同的位置都要配有不同的锚点,布满全图所使用的锚点也是全图的。
将图导入Unreal中后打开Widget的Designer中选中刚创建的image在其Detail面板中找到Appearance,有Brush和Color and Opacity,在Case1中介绍了Color and Opacity,这里就只说Brush,点击Brush就可以看到一些选项,image就是供给添加图片的,Image Size可以调节图片的大小(像素),Tint(染色剂)可以对image进行染色。Draw As ,Tilling接触到了在详细解释。(这里做一个小插曲,差一段有关Button的一些Detail,在Slot(槽)中的Horizontal Alignment(横轴准线)和Vertical Alignment(竖轴准线),调整这两个属性可以调整目标的位置,这个对于其他的控件也可以使用,Appearance中有Style,Color and Opacity,Background Color.其中重点说一下Style,点开Style,这其中的设置就是对Button的本身的编辑,Normal(平常的状态)Hovered(悬停:指的是鼠标悬停在Button的时候)Pressed(按下)还有一些Sound可以设置鼠标在对Button的作用时设置声音,另外一些Padding有机会再说。
基本达到这种简易的效果就可以了,具体优化(色彩,字体)这里不详细做,主要是完成事件。
进入Graph进行编程,这里要对三个Button进行编辑,那么驱动当然就是点击Button了,在这里Button是默认的Is Variable,所以不用在Designer中修改,如果想要对Vertical或者Horizontal进行编辑,就要设置Is Variable了。选中Button在Detail中寻找Event会发现有(On Clicked,On Pressed,On Release,On Hovered,On Unhovered)的事件,意思分别是(点击,按下,松开,靠近,远离)这里我使用点击事件进行编辑。先对PlayGame编辑,在OnClicked驱动后引出节点OpenLevel并输入LvevlName,这里我输入了Case1中的Level,在OpenLevel后引出Remove from Parent节点,节点目标是Widget,很明显就是为了移除控制蓝图而设定的节点,我们在打开Level的时候就必须要移除这个出现在镜头屏幕上的Widget,目标就是self.设置完之后,不妨先试试效果。在LevelBlueprint中用Event BeginPlay驱动出Creat Widget,在后面接着引出add to viewport.如下,Case1中就说明了这是实现UI的程序
这里会发现有一个Zorder的int类型成员数据,它的作用是将Widget进行排序,例如在Main(Widget Bluepeint)中ZOrder被写做1,而HUD(Widget Blueprint)中的ZOrder的值为0,则Main在前,HUD在后。(补充一点,如果两个都没有进行编辑,都为0,那么在使用sequence情况下,会以sequence的顺序进行排序,Then0在后,Then1在前。)
以这种状况去调试的话,你就会发现问题,没有鼠标怎么点击Button,那么就是说我们在进入Level中面对主菜单,是需要鼠标进行选择操作的所以我们在Add to viewport后面再加上一个设置鼠标出现的节点,set show mouse cursor(cursor:光标)。这样就可以去尽情调试了。
接下来就是编辑QuitGame的事件了
以上两种方式都是可以的,唯一的区别是Exevtue Consloe Command是控制台的命令,如果打包成游戏的话就会失效,游戏中一般不会将控制台打包的。所以最好使用Quit Game的节点。
对于Option 的编辑大概思路是点击Button就跳转到下一个Vertical,可以通过Set Visible来实现,点击Button就显示下一个Vertical,隐藏这个Vertical.并且在下一个Vertical中还要设置一个Return的Button来返回,同理使用Set Visible。
例如这就是我写的Option,写号之后将这个Vertical移动到跟上一个Vertical一致的地方(覆盖),现在会出现后者把前者覆盖的情况,这是我们不愿意看到的,我们想要的结果是点击Option显示后者隐藏前者,那么在初始的时候我就将后者设为不可见。选中Vertical在Detail面板中的Behavior(行为)中的Visibility选择Hidden.(在Behavior中还有个Is Enable的作用是使其有效,例如Button是Is Enable的,那么Button是可以点击的,反之,Button仍然会出现在UI中,但是不能点击),还有一点就是将这个Vertical的锚点设置成与上一个Vertical的锚点相同的位置。下面就可以对Option进行编程了。
这样我想要的基本效果就出来了,大概的编程逻辑就是这样。
彩蛋(以上的逻辑事件都是在Level中实现的,这里最地道的游戏编程应该将UI的东西存放在Game Instance中,Game Instance是整个Unreal的逻辑最高的地方,游戏的整体逻辑编辑的地方,可以说是架构,当然它是跨关卡的,可以在任何关卡中随意调用成员变量和函数,在正规的游戏编程中,UI是编辑到Game Instance中的,这样在其他管卡一样可以调用了,不需要每个关卡都写一遍。之前我都把UI的实现放在LevelBlueprint中写,那么现在可以把这些东西封装起来放在Game Instance中,这里举个例子,将这个Case中的Main的实现封装在Game Instance中:
创建一个Game Instance的类,在Blueprint中创建一个函数,这时候就要构思一下这个函数如何封装才能达到我们要的效果,那么就得看一下没有封装前的样子了;
这样的话函数的封装主要是看其中的Input和output,从上面得知,封装函数需要一个User Widget class的input。封装之后就是这个样子,
这里在Level中使用get Game Instance和Cast to MyGameInstance从而直接从变量As My Game Instance中引出函数Main也算是一种信息传递的方法,不过这种特使的方法是有局限性的,例如在系统中可以Get到的特殊的类才可以通过Cast to 传递信息,例如GetPlayerController,GetGameInstance,GetPlayerCharacter,等。当然还有一种封装时将创建的Widget的变量给导出来,就像这样:
这样做的目的是将创建好的Widget提升为变量导出,可以供其他使用,例如Remove from parent.)