头脑风暴
● 做什么:Slate是UE底层的UI框架
● 解决什么问题:Slate是纯代码实现,能够实现更加复杂的功能
● 设计哲学:Slate是跨平台,快速迭代、高性能的UI框架
Slate概述
● Slate完全由C++实现,它的布局与控件的创建只能用C++实现(Slate支持更底层的组件,可以开发更加复杂的功能)
● UMG是基于Slate封装(Slate的UObject性质的一层封装)可视化编辑器,拓展了很多事件与方法,支持BP
Slate使用
1 声明式语法
● SLATE_BEGIN_ARGS与SLATE_END_ARGS这两个宏之间,添加自定义Slate控件参数与参数默认值
● SLATE_ATTRIBUTE(变量类型,变量名)
● SLATE_EVENT(变量类型,变量名)
● SLATE_NAMED_SLOT(FArguments,插槽类型,内容)
● 初始化: 在宏声明后,参数名变成 "_" + "宏里面的变量名",如"Label",参数名为 "_Label"
class SCustomWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SCustomWidget)
:_Label(TEXT("Label"))
{
}
/** 将显示在按钮上的标签 */
SLATE_ATTRIBUTE( FString, Label )
/** 单击按钮时调用 */
SLATE_EVENT( FOnClicked, OnClicked )
/** 将放置在按钮上的内容 */
SLATE_NAMED_SLOT( FArguments, FSimpleSlot, Content )
SLATE_END_ARGS()
};
2 传递参数
通过宏中声明的参数在类成员变量之间的传递
如SLATE_ARGUMENT(ArgType, ArgName)这个宏
这个宏的作用是,向FArguments中添加声明的变量
class SCustomWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SCustomWidget)
:_Label(TEXT("Label"))
{
}
/** 将显示在按钮上的标签 */
SLATE_ATTRIBUTE( FString, Label )
SLATE_END_ARGS()
public:
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
private:
FString Label;
};
void SMyCompoundWidget::Construct(const FArguments& InArgs)
{
/** 通过Construct函数获取Label的值 */
Label = InArgs._Label;
/** 在其他地方就可以使用这些自定义值 */
HorizontalBox.AddSlot()
[
SNew(STextBlock)
.Text(FText::FromString(Label))
];
}
3 构建对象
● SNew是Slate中构造对象的方法,返回一个TSharedRef对象
● [] 语法糖,实现方法是C++的运算符重载,本质是向SLATE_DEFAULT_SLOT中添加内容
● SNew().SectionName() 这种是链式函数调用
● + 语法糖,运算符重载,相当于加一个Slot
// 为静态网格体添加一个新的部分
ContextualEditingWidget->AddSlot()
.Padding( 2.0f )
[
SNew( SDetailSection )
.SectionName("StaticMeshSection")
.SectionTitle( LOCTEXT("StaticMeshSection", "Static Mesh").ToString() )
.Content()
[
SNew( SVerticalBox )
+ SVerticalBox::Slot()
.Padding( 3.0f, 1.0f )
[
SNew( SHorizontalBox )
+ SHorizontalBox::Slot()
.Padding( 2.0f )
[
SNew( SComboButton )
.ButtonContent()
[
SNew( STextBlock )
.Text( LOCTEXT("BlockingVolumeMenu", "Create Blocking Volume") )
.Font( FontInfo )
]
.MenuContent()
[
BlockingVolumeBuilder.MakeWidget()
]
]
]
]
];
Slate设计哲学
作为一款游戏引擎的UI框架,必然需要考虑到游戏运行时和编辑器两种UI方式。在设计上,可以设计一种UI框架既可以用于游戏运行时,也可以用于编辑;也可以设计一种UI框架用于游戏运行时,另一种UI框架用于编辑器。在设计上,最好的方式当然是一套UI在游戏运行时可用,在编辑器开发也可以用。作为一款游戏引擎的UI框架,跨平台、高性能也是必不可少的。UE在设计UI框架的时候,需要考虑这些问题:
- 既可以在运行时使用,也可以在编辑器开发使用,最好是一套UI框架
- 在跨平台上表现良好,在性能上表现也很优秀
- 开发效率高,UI设计方便与迭代,控制数据流
- 对于程序员来纯粹一点,使用C++,不需要引入其他语言
1 大名鼎鼎的IMGUI
IMGUI是一款纯代码(C++)驱动的GUI系统,支持游戏运行时和编辑器模式,跨平台、无依赖、支持OpenGL、DirectX等多种渲染API,Unity也是用的这种UI框架。IMGUI可谓是大名鼎鼎,可以在这个仓库找到IMGUI。那么是否考虑将IMGUI作为UE的UI框架呢?
优点
● 程序员喜欢 UI 描述“接近”代码,易于获取数据。也就是说,直接用代码(C++)来写UI,不需要额外的(xml,css)等来制作UI。
● 失效不会成为问题,直接轮询数据即可。IMGUI是每帧轮询的。
● 易于程序化构建界面。C++,用循环结构,New界面对象的艺术。
缺点
● 添加动画和设计较难
● UI 描述为命令式代码,因此无法将其设为数据驱动
2 Unity中三种UI系统
Unity中有三种UI系统,分别是IMGUI,Unity UI (UGUI) 和UI Elements(UI Toolkit)。在设计哲学上,Unity早期,用IMGUI来作为编辑器开发,UGUI为游戏运行时开发,后来新版本中,推荐用UI Elements。
在最新的Unity6中,推荐使用UI Elements(UI Toolkit)。UI Elements 其实就是类Web的方式实现,界面由。uss和uxml组成,相比IMGUI,就是一坨答辩, 不推荐学习。
3 UE中Slate与UMG
想象一下,以UE追求性能的极致,又特别偏爱蓝图的性格,参考隔壁Unity那好几套UI系统的设计肯定参考不来,肯定想设计一套UI既可以用于运行时也可以用于编辑器,而且又要性能高,设计又方便。突然有一天,灵机一动,参考IMGUI那样,用纯代码实现作为整个UI的底层框架,于是Slate诞生了。然后将Slate用UObject封装变成蓝图可视化,于是UMG诞生了。
相关资料
UE5官方 Slate概述
【Unity基础】Unity中的UI系统
【UE5】使用Slate进行UI开发与编辑器拓展(一):Slate简介
UE4 Slate to UMG<0>