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

斯坦福UE4C++课程P66-P69游戏标签GameplayTags

2022-11-11 16:01 作者:_Hide-on-bush_  | 我要投稿

FGameplayTag:(F开头表示是结构体)

  • FName wrapped in Struct 用结构体封装的FName

  • Alternative for:bool,enum,FName 能够被bool、enum、FName替代

  • created via Project Settings 通过项目设置创建

  • Editor support to easily select GameplayTags 从编辑器可以轻易处理GameplayTags

  • FGameplayTagContainer(Wrapped TArray of GameplayTags)FGameplayTagContainer使用TArray作为GameplayTags的容器

  • Extensively used by GAS 在GAS中被广泛使用

作者给了一些GameplayTags的学习资源,主要是官方文档。

首先我们到ActionRoguelike.Build.cs构建文件把GameplayTags模块包含到项目中,这样我们就能在C++中使用GameplayTags了。

在SActionComponent类中添加

权限给满,因为我们稍后要在蓝图里使用它,纯粹为了方便。

这里我们不使用指针,所以必须包含该结构体的头文件(编译器需要知道该变量的大小),如果是指针,其大小是固定的,就无需包含头文件。

FGameplayTagContainer中可以加是否正在冲刺、是否正在攻击、是否被击倒的这些信息。然后其他系统可以从这个容器中获取到这些信息,玩家目前在做什么,然后以此为依据去做决定。

下面我们在SAction类添加

在Action启用时,我们把GrantTags中的所有Tag都放入ActiveGameplayTags中;停用时全部移出:

BlockedTags先不加,我们在SActionComponent类TickComponent函数添加debug信息,看看效果再说:

我们让ActionComponent附加在的Actor名字、因Action发出而附加的Tags打印出来。

编译,进入project settings->GameplayTags->Add New Gameplay Tag,新建两个tag:

"Action.Sprinting"、"Action.Attacking"

到Action_Sprint蓝图,发现右侧Tags多了Grants Tags、Blocked Tags

调整如下:

ActionSprint蓝图下

表示我们希望冲刺时会生成Action.Sprinting的标签,且会受到Action.Attacking的阻止(冲刺时不能攻击)。

在其他SAction继承蓝图类也调整tags:

Action_MagicProjectile、Action_Dash、Action_Blackhole下

表示发射projectile的三种action都算Attacking,且冲刺时无法施放。

现在我们攻击时(魔法球、Dash、黑洞),debug信息出现在左上角。

接下来我们添加冲刺时阻止攻击、攻击时阻止冲刺逻辑。

在SAction的public下添加

函数体:

在SActionComponent添加判定,如果CanStart函数返回false,就不能开始Action。

我们还添加debug信息,表示如果当前不能开始此Action,就跳过当前循环,判定下一个Action,并打印失败的Action名字

如果存在不能开始的Action,因为我们在SAction_ProjectileAttack类中写了,一旦startAction函数执行,最后一个语句会执行stopAction。但存在不能开始的Action的话,我们就没有添加过tag,执行stopAction移除tag会出现错误。

所以我们在SAction添加一个bool变量,和获取它的函数:

StartAction_Implementation函数末尾加上

StopAction_Implementation函数末尾加上

并在开头添加

表示如果从未执行过StartAction,就不要执行StopAction。(PV操作的感觉??)

现在编译运行游戏,攻击时冲刺,打印"Failed to run:Sprint";冲刺时攻击,打印"Failed to run:PrimaryAttack"。

但现在攻击时仍能攻击。

在CanStart函数开头添加:

表示,如果一个action正在执行(还未执行stopAction),那么就不应该重复执行该action。

现在仍有一个问题,就是扔魔法球时虽然不能扔魔法球了,但可以扔Dash和黑洞出去。

我们只需添加blocktag即可:

现在攻击时,会阻挡攻击action。

疯狂按鼠标左键/R

意思就是,一个action执行,要执行另一个,将会把其信息打印在屏幕上并失败。

下面我们用游戏标签添加门和钥匙系统。

首先到project settings新建三个tag

更改leverBP如下:(Tag提升为变量,命名KeyCard)

lever改造成获取开宝箱的钥匙机关,注意Key Card暴露在编辑器

在宝箱TreasureChest蓝图的Interact事件后添加(之前写的开宝箱的逻辑不变)

注意Required Key Card暴露在编辑器

Has Tag节点判断Active Gameplay Tags中是否有Required Key Card作为Branch条件,表示如果tag匹配,才能开宝箱。Exact Match表示,只有tag完全一致才返回true。

我们可以给场景中实例化的宝箱分配三种颜色之一的tag,同理给杠杆lever分配tag。现在只有lever的tag和宝箱的tag相同,才能在和lever交互后获取到相应tag,才能开相应宝箱。

如果我们取消勾选Exact Match,表示Required Key Card属于Active Gameplay Tags中的一类Tag就行。举个例子,我们取消勾选Exact Match,然后一个箱子设置Required Key Card为KeyCard,一个设置KeyCard.Blue,和lever获取到KeyCard.Blue,那么只要和lever交互,就能够开这两个箱子(一个完全匹配(Exact Match,KeyCard.Blue==KeyCard.Blue),一个只是一类(KeyCard.Blue属于KeyCard,也能开))。

这一P我们学习用GameplayTags抵挡攻击(parrying mechanic)。

首先添加tag:Status.Parrying。

在魔法球C++类OnActorOverlap函数添加

现在测试,我们先到角色类蓝图Action组件,设置Active Gameplay Tags添加Status.Parrying,这样角色一出生就有这个Tag,便于测试。然后我们给魔法球勾选Status.Parrying,表示给C++的ParryTag赋值为Status.Parrying。

现在AI攻击玩家,玩家会反弹魔法球:

下面我们给AI角色添加Action组件。头文件添加ActionComp,构造函数初始化组件。

AI蓝图勾选Status.Parrying,让AI一开始也有此Tag。现在AI发射魔法球,打到玩家反弹,反弹到AI又会反弹,直到反弹到打不中二者,而击中墙壁为止。玩家攻击AI也是 一样。

我们稍微修改,让玩家按R能够有反弹能力1秒。

新建Action_Parry,继承自SAction(首先要在C++给Stop Action函数添加BlueprintCallable,让我们可以在蓝图调用;且需要调用父类节点,实现基类功能):

按R开启反弹Action,1秒后自动停止

在Input->Action Mapping,新建名为Parry的Action映射,键为R(黑洞改为E,交互改为F)。我们取消勾选玩家和AI的开局就有ParryTag,给玩家添加Action_Parry的能力(在Default Actions数组新添加Action_Parry)。

在角色蓝图把R键和Parry动作绑定(C++中就是BindAction):

现在玩家按R,就开启了1秒内的反弹能力。

最后作者加了AI受伤害时,伤害数字的显示,之前我做过了。

还有AI血条的位置可以用之前做的World Offset来调,我们给z方向上加90,让血条被创建在AI头上。

斯坦福UE4C++课程P66-P69游戏标签GameplayTags的评论 (共 条)

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