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

斯坦福UE4C++课程P63-P65游戏能力系统GAS

2022-11-10 15:28 作者:_Hide-on-bush_  | 我要投稿

GAS(Game Ability System),在课程里我们称之为Action Component/Action System,也是为了避免把所有代码写到SCharacter而使用的东西。

  • 虚幻引擎的针对abilities、buffs、attributes的框架(和Gameplay框架完全分开,所以和GameMode、PlayerStates、playercontroller这些类无关)

  • 强大的RPG游戏功能集、适配广泛的游戏类型(对包含少量actions/abilities的小型游戏可能有些不必要)

  • 陡峭的学习曲线,没有大量的文档

作者给出了一些GAS的学习资源,主要是官方文档、github.com/tranek/GASDocumentation(比官方文档详细)。

下面我们准备创建我们自己的'Action System',比直接在角色类写代码拥有更多的灵活性(针对abilities、buffs)。之前我们创建的Attribute组件类其实就是一个类似于GAS的类。

GAS代码分离:

  • 避免单个类包含所有的关于ability、VFX的代码

  • 一种用途的类更易维护(e.g. Action_MagicProjectile, Action_Sprint)

  • 更好的协作,尤其是针对蓝图(版本控制中无法合并二进制的资产)

其他好处:

  • gameplay时,可提供Abilities、Buffs(e.g. level-ups、gear upgrades、damage-over-time effects)

  • 避免通过“硬链接”一次把整个游戏加载到内存(GAS更多是通过软链接)

  • 可通过GameplayTags管理大量的state和labels,而不是booleans或者enums(e.g. 'DamageType.Melee.Slashing','Action.IsSprinting','Pawn.Mage','Pawn.Warrior')

  • 不仅仅Player能用Abilities,世界中的actors也能用Actions

这一章我们要做

  • SActionComponent.h(ActorComponent)

  • SAction.h(UObject)

  • 首个Action:Sprinting冲刺

  • 重构Projectile abilities(扔魔法球、Dash球、黑洞),从SCharacter.h移到Action

SActionComponent.h

SActionComponent.cpp

SAction.h,UCLASS里加Blueprintable是为了能够被蓝图继承

SAction.cpp(后面可以在蓝图重写这两个函数)

另外,在SCharacter添加Action组件,以及我们要添加的冲刺函数:

在构造函数实例化ActionComp

绑定输入Action:(按住左shift冲刺,松开停止冲刺)

SprintStart、SprintStop函数:

现在编译,我们在蓝图里实现冲刺能力Sprint ability。

由于我们给SAction类加了Blueprintable,所以可以在内容浏览器创建蓝图时看到它。我们创建蓝图Action_Sprint,继承SAction,并添加一些冲刺的逻辑。后面我们写projectile ability逻辑仍在C++里实现。

现在打开蓝图,我们在右侧可以看到类默认值有Action Name,填上Sprint;左侧可以点击重写StartAction、StopAction函数,弹出两个节点。

我们可以右键点击该两个节点,选择调用父类(在C++里有一句UE_LOG的函数),表示打印该Action名字在日志里。

另外,我们需要在project settings->Input添加action,名为Sprint,键为左Shift。

最后我们在角色类蓝图添加该Action:

表示将实例化的Action Sprint蓝图类添加到ActionComp中。

现在按住左shift加速,松开回到正常速度。

这种添加角色ability的方法,仅仅在角色类蓝图添加了Action,没有硬编码的程序,所有具体的ability逻辑都在Action_Sprint蓝图实现。

下面我们在C++中把三种Projectile逻辑(魔法球、Dash球、黑洞)转换为Action。

新建C++类,继承自SAction ,命名为SAction_ProjectileAttack。SAction_ProjectileAttack是三种projectile继承的基类(把Dash、黑洞也看成Attack罢了)。

在此类中,我们需要重构projectile的基本功能(从角色手中发出、向十字准星发出、各种component),只需要从SCharacter搬过来。

SAction_ProjectileAttack.h

SAction_ProjectileAttack.cpp,从SCharacter照搬的代码需要改动一点。

其中获取相机组件位置的语句可以用InstigatorCharacter->GetPawnViewLocation()代替

SCharacter的PrimaryAttack函数改为:

编译,回到内容浏览器,新建继承自SAction_Projectile的新魔法球攻击蓝图类Action_MagicProjectile,在右侧details按之前的魔法球设定选择资产,ActionName选为"PrimaryAttack"。最后一步,我们需要给角色分配该ability,在角色类蓝图AddAction即可。

现在成功移植魔法球攻击能力。

接下来可以移植Dash、黑洞能力。

只需要在SCharacter改写BlackholeAttack、Dash函数:

然后duplicate新魔法球攻击蓝图,命名为Action_Dash、Action_Blackhole,按原来的设定分配资产;

但现在有一个问题,需要在角色类蓝图一个一个添加ability,我们可以在ActionComponent创建一个array来添加ability(之前在ActionComponent添加的Actions是组件中所有可能存在的能力TArray<USAction*>,而这次我们创建的是我们要让角色使用的能力TArray<TSubclassOf<USAction>>),要让角色用该能力就放进去,不要就从中移除。

这样一来,只需最后在角色类蓝图右侧Default Actions(我们在ActionComponent新加的array的名字)添加四个abilities蓝图类(魔法球、Dash、黑洞、Sprint冲刺)即可。无需beginplay->addactions->addactions->addactions->......了。

角色现有能力

此外,把C++中老代码全部删除。

下一章我们学习GameplayTag。其作用,比如我们希望角色冲刺时不能发射魔法球,发射魔法球时也不能冲刺。现在我们发射魔法球动画播放时仍可以发射第二个魔法球,只要我们手速够快,每帧都能发射一个魔法球出去,所以可以限制攻击时不能再次攻击。

我们同时按鼠标左键(魔法球)、Q(Dash)、R(黑洞),它们可以同时发射,因为我们并没有限制它们。


斯坦福UE4C++课程P63-P65游戏能力系统GAS的评论 (共 条)

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