欢迎光临散文网 会员登陆 & 注册

斯坦福UE4C++课程P23-P27UMG&玩家属性

2022-10-27 18:24 作者:_Hide-on-bush_  | 我要投稿

我们想把像血量、护甲、强壮度等玩家属性加入到游戏中,最直观的是放到角色类SCharacter中。这样到最后,角色类可能包含成千上万行代码,维护起来很麻烦。

所以我们把这些放到Actor Component中,作为角色类的组件来使用。

我们新建一个SAttributeComponent类,作为角色的属性类。

先了解下UPROPERTY宏的参数的意义:

在新建组件类中给健康值加上EditDefaultsOnly和BlueprintReadOnly。

组件cpp文件把健康值初始化为100,再写一个修改生命值的功能

在角色类中添加上该组件,在蓝图编辑器中将看到该组件

接下来在魔法球C++类添加重叠事件触发修改角色生命值函数。

现在魔法球打到角色身上,生命值都会减少20。

现在我们进入UMG(Unreal Motion Graphics)部分。

内容浏览器下创建UI-Widget Blueprint进入到控件蓝图,在左边除了可以添加默认自带的控件外,还可以直接添加之前我们做的十字准星控件。

我们首先拖进来一个文本框和进度条(想要更好的进度条可以用图像、shader effect、材质)

接下来我们想要让右侧数字和角色生命值绑定,最常用的方式是属性绑定,即点击text控件右侧create bind。本质上是创建了一个每帧调用的函数。

创建之后来到函数编辑界面。为了便于了解函数功能(函数一多就不容易了解功能),我们把函数get text 0更名为GetHealthText。

现在我们没有给返回值输入任何东西,如果在角色类create widget和add to viewport之后,只会看到进度条。

我们给返回值输入99之后

可以看到99被显示了出来

接下来要绑定角色属性组件的生命值,可以这样连

注意text是粉色线,字符串是粉红线,两者并不等价。

tip:UE4中的'string types'

  • FString:debug用的最多;允许字符串操作(append,split...)

  • FName:使用哈希映射,使得字符串比较更快;在系统和gameplay逻辑中用的多(eg. GetMuzzleLocation(FName));一经赋值就不能被改变

  • FText:Front-end text to display in UI;Easily 'localized' into different languages

像之前我们在角色类查询角色手骨骼位置的

就是使用FName来查询“Muzzle_01”的。

现在效果如下:

之前的text绑定函数方法是每帧调用,效率比较低下,比较好的办法是在血量改变时才改变该text值,这就好比别人只需告诉你一声比你自己每帧都询问效率高。

解决办法是,这里在AttribureComponent类添加DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(DelegateName, Param1Type, Param1Name)宏。

注意:UE4宏参数有如下规则,类型和参数之间也要加逗号。

最后添加了4个参数:

我们需要编写委托事件FOnHealthChanged,当其发生时,才进行血量变化。

添加以下语句,assignable表示可以在蓝图中进行绑定操作

再在cpp文件中把事件插入到合适的位置:

当血量加上改变值delta之后,委托事件把Instigator、OwningComp、NewHealth、Delta进行了填充。

现在编译之后,打开角色蓝图,选中AttributeComp,可以看到右侧细节的事件栏多了OnHealthChanged。

我们测试一下,当血量改变时才打印血量值

点击On Health Changed绿色+号,跳转到蓝图,像如下连线

达到预期效果。

现在把功能从角色蓝图移到UI绑定函数中;

在PlayerHealth控件蓝图中,当控件被构造时,我们获取到控件拥有者pawn类,转换为C++SCharacter类,获取到其中的AttributeComp组件,从该组件节点拖出蓝线搜索assign On Health Changed,在事件分发器栏下选中目标节点,该节点将之前我们C++里写的事件OnHealthChanged被绑定到目前的控件蓝图。每当该事件发生时,我们设置进度条也会改变(血量/100得到血量百分比,赋值给进度条)

现在效果如下:

血量最大值我们是直接在蓝图里设置的100,不便维护,所以我们使用在C++里定义的Health=100。在蓝图如下连:

GetClass获取到事件拥有组件(角色attribute组件),然后GetClassDefaults获取到该组件类所有属性(我们只定义了Health,所以只显示它)。

作者指出,他的学生经常在角色蓝图创建控件后把控件提升为变量存储下来,然后直接原地更新Health。因为我们希望让UI去获取角色的值,在UI逻辑里更改,而非在角色类去获取UI改变其中的值,所以这种做法不推荐。

另外一点,Pre Construct引脚拖出去执行的逻辑会在该控件被添加到UI之前执行,而Construct和BeginPlay一样在游戏开始时才执行。

我们可以在预构造事件里设置进度条颜色为红色,编译后进度条在Designer里就是红色;但在构造事件里设置的话,在运行游戏后进度条才显示为红色。

接下来我们介绍控件蓝图中的动画。原理是关键帧key frame。

我们可以在左下角新建一个Animation,命名为PulseHealthAnim,选中它之后,可以点击右侧details的参数,为这些参数添加关键帧。

我们为文本设置3个关键帧,初始末尾scale为1,中间为1.2,按空格播放,效果如下:

现在在蓝图拖出该动画,连在最后:

现在只要角色被击中,就会播放该动画。

最后我们让玩家撞击爆炸桶时会给玩家扣50血:


斯坦福UE4C++课程P23-P27UMG&玩家属性的评论 (共 条)

分享到微博请遵守国家法律