https://www.unrealengine.com/marketplace/zh-CN/product/content-examples
《内容示例》是学习UE5的基础示例,可以用此熟悉一遍UE5的功能
UI示例
- UI_UMG :基本UMG
- UI_CommonUI :UMG多层应用
- UI_SlatePostBuffer UI :FX的示例,UI在全局效果的使用
UI_UMG示例
开始:关于UE5的程序启动(入口)
示例需要了解UE5程序入口,一般先要注意3处地方:
- 项目设置->地图和模式
这里可以配置GameMode与GameInstance;如果配置了,会启动对应的程序;如以下表示没有做任何配置(另外需要注意 项目设置->输入,这里会配置一些操作映射)
- 世界场景设置
这里可以配置GameMode,与第1条是重复的配置,这里的配置会覆盖第1条的配置。
如果看到GameMode有配置,点下放大镜,可以找到并打开此GameMode蓝图
看到GameMode_UMG蓝图中,被更改的类
从这2处地方收集到,入口程序需要关注的:GameMode_UMG、BP_PlayerController_UMG、MyCharacter_UMG这3个程序。
- 关卡蓝图
另还有一个地方需要关注:打开关卡蓝图,查看有没有启动的程序代码
开始:关于GameMode、PlayerController、Pawn等关系
- 在写程序时,很难规划好,什么功能写在pawn里,什么功能写在playerController里
- Pawn是角色,写角色的功能和接口,比如坦克可以开炮和行动,开炮和行动的功能写到Pawn,并提供控制接口。AI或Player是负责操作接口进行控制。
- PlayerController处理操作Pawn提供的接口,还需要操作UI、关联Input和摄像机运动等,承担了更多的控制工作
- 但也有很多程序并不这样编写。是把功能直接集成到Pawn里。
- 那这几个类,哪个类是先执行的?经测试(按print字符的先后);
发现顺序是:
- PlayerController
- 规则根据组合情况而不同,包括GameMode、Pawn、Actor,是不确定的运行顺序
- Pawn单独运行时,顺序高于PlayerController,但拖入Actor蓝图中,顺序就低于PlayerController
- Player Start:玩家的起始位置
可以把Pawn拖入场景,选择下Player 0等配置,等效于Player Start
在入口类GameMode、PlayerController、Pawn等中,只有Pawn是可以被投入场景(Outliner大纲)中的
开始:UE5入口的思考
以上UE5提供的入口思维,似乎已经完美解决了问题。
但是,有一个问题在这样的结构下,显得不好操作:
一般我们做项目,需要做一些项目的配置,比如UI的首页是什么,默认有哪些模型先显示或运行、或者读取外部的哪些数据或图片等。
那这些配置的功能要在写在哪里呢?若按照UE5的入口规则,需要在GameMode(或者GameInstance)里进行配置,比较符合UE5的原意。
只是GameMode配置,要么在蓝图中,要么在变量中,这2处都不是很好配置。
熟悉Unity编程的同学,会习惯于在项目窗口里配置(相当于UE5的Outliner大纲里),会制作Manager对象完成配置工作。
个人感觉,同样可以制作Manager对象,结合世界场景设置,用PlayerController启动配置对象,来完成UE5的入口配置问题。
1.1 Sliders
-
MyCharacter_UMG:
分为3类功能:控制UI的功能(显示、隐藏等)、控制角色移动的功能(鼠标看、走、跑)、生命值的功能 -
MyCharacter_UMG - UI功能:
BeginPlayer是定义了一个Exit的UI
ShowElement:Lock Input UI是只使用UI模式;ShowElement把UMG类Create后加到屏幕Viewport中;并把Exit HUD(退出按钮的UI)也加到屏幕中。做了一个HUDActive的状态标记。
若Lock Input UI为false,则触发UI后,角色还是可以继续走动。
HideElement:隐藏UI -
BP_EventDemoTrigger,触发器
触发器可配置一个要显示的蓝图类、3DWidget还是HUD、是否Lock Input to UI
Event ActorBeginOverlap:当触发它的触碰区域后,默认会触发这个事件
关于bool值的用法思考:
bool值有用于配置项的、有用于状态记录的,还有其他适合bool值的参数
如果是配置项的,可以If开头;状态的,可以Is开头;
关于状态的设计思考:
一个对象对外开放控制的接口,状态应该隐藏在接口里面,抽象出若干事件作为接口
参考软件的设计模式 - 状态模式
MyCharacter_UMG抽象出了ShowElement与HideElement 2个接口
另外,把Current Button(触发器)的对象传给UI,是为关闭UI时,同时触发触发器模型的灯的关闭;
- BP_PlayerController_UMG
FreeMouse:显示鼠标
BindMouse:游戏模式
按照PlayerController与Pawn的分工,UI操作可以放在PlayerController里,不需要2个地方都放起来
触发过程:
- BP_EventDemoTrigger触发Overlap,找到Pawn(Character),为Pawn赋值触发器对象与UI类,然后运行ShowElement;
- ShowElement, 先CreateUI,加入屏幕,设置鼠标与UI操作模式
- UMG_Sliders
Begin:通过PlayerController设置下鼠标状态
这里使用了Text的绑定函数的功能,个人不推荐在实际项目中使用
- 当使用 Show Only Modified Properties来查看哪些属性被修改了时,而这个绑定是筛选不出来的
- 编程东一点西一点,就完全没有线索了
可以使用Sliders的OnValueChanged简单实现
1.2 Buttons
- 通过在Text的Visibility绑定Get Visiblity_0的函数,实现Text的隐藏;实际项目中,不推荐绑定的做法。
- 如何快速地 创建或定位 一个Button的OnClicked事件
在Designer里,选中某Button;切换到Graph视口,此时Variables会选在Button上;在右边能看到Events列表,点击创建或定位
1.3 Input
- UI里有3个组件:SpinBox,ComboBox,CheckBox
SpinBox取值
ComboBox判断是否有选择,示例是判断获取的值是否为空,其实可以判断Index值,没有选为-1
ComboBox取值
CheckBox取值
1.4 Nested widgets
- 嵌套UI,主UIWidget_NestedWidgets,在右侧有一个Scroll Box,是放嵌套的UI
- 这里蓝图写得有点乱,主要2个功能:
- 创建Widget_PlayerEntry的UI,嵌套在框中
- 当Input里的值改变时,改变嵌套的UI里的值
这里用到PlayerData结构体
在Widget_PlayerEntry中,绑定各文字框的值
在主UI中,当Input的值改变时,重新组成PlayerData数据,并赋给Created Widget
2.1 Progress Bars
- 通过2个按钮,增加或减少Progress Bar Percent的值,并判断下这个值的上下限;并给Progress Bar 赋值
- 可以打开Hide Unrelated的按钮,清晰看到一条蓝图的主线
2.2 Progress Bars
- 与上面示例的差别:值是在MyCharacher_UMG里health值
- 调用了Increase health接口来增加health值
Cast To是非常消耗性能的,所以要在Begin的时候,先做一遍Cast to保存起来
另外,绑定的函数里,使用Cast To性能消耗太大
2.3 3D Widgets
- 这里采用了BP_EventDemoTrigger_3D,而非BP_EventDemoTrigger
就是说,BP_EventDemoTrigger里的Show3DWidget这个配置项是假的,Display HUD也是无用的 - BP_EventDemoTrigger_3D里有一个3dWidget的组件,初始为隐藏,通过Overlap,来控制显示
讨论下,如果使用原来的触发器,要怎么实现:
把3D Widgets单独做一个蓝图Actor,放到场景中
触发器会触发PlayerController(这里是Pawn)
PlayerController可以根据tag,找到3D Widgets,触发显示3DUI(tag的名字可以和蓝图类名一致)
2.4 Widget Animation
- UMG的Animations功能,示例有Bounce和Scale 2个动画(另外一个动画是无用的)
- 如何启动动画?
如果Loops这里设置成0,即为循环 - 如何停止动画?可以使用单独动画停止,或全部动画停止
- 如何全部播放动画?
可以先建立一个动画数组,然后循环播放
3.1 Images
- 此示例边上有一个摄像头,拍摄人物的动画,并实时渲染到UI中
- 摄像机的蓝图RenderCapture,里面有Camera和Scene Capture Component 2D 2个组件;
Scene Capture Component 2D选了RenderTarget图片;用于实时拍摄保存。
- 建立一个材质 M_RenderTarget,材质类型是User Interface
- 图片绑定这个材质
一个问题是,这张图片的色彩太暗了,如何配置成和实际场景的色彩差不多呢?
在Scene Capture Component 2D进行一些配置
对环境光的亮度进行一些调整
对RenderTarget图片的大小也可以调整
最后调整下UI里的图片比例,呈现出合适的效果
3.2 Widget Slots
- 在Canvas Panel中,可以通过设置图片的Slot,重新设定位置(这个写法比较特殊,需要Cast To)
3.3 Loading Icons
- 这里展示了3种进度条:CircularThrobber、Throbber、ProgressBar
- Throbber可以放一张图片作为加载效果,可以设置多个块(Number Of Pieces)
3.4 Alignment Options
- 3种布局方式:Horizontal Box、Vertical Box、Uniform Grid Panel
- 其中Horizontal Box、Vertical Box是自动布局的,随便拖一些组件进去,就会横向或纵向自动局部
- Uniform Grid Panel是需要在子元素里,设置行列2个值,才能定位在正确的位置
- 这样总要去写这个2个值比较麻烦,可以做一个蓝图去自动实现
本示例就学习完毕,欢迎同学一起讨论指教,本人微信:canchs