Language:
Page Info
Engine Version:
Share

游戏性技能

GameplayAbilityTopicImage_01.png

游戏性技能(Gameplay Ability) 源自UGameplayAbility类,定义了游戏中技能的效果、使用技能付出的代价(如有),以及何时或在何情况下可以使用等。游戏性技能可以作为异步运行的实例化对象存在,因此你可以运行专门的多阶段任务,包括角色动画、粒子和声效,乃至根据执行时的用户输入或角色交互设计分支。游戏性技能可以在整个网络中自我复制,运行在客户端或服务器计算机上(包括客户端预测支持),甚至还能同步变量和执行远程过程调用(RPC)。游戏性技能还使引擎可在游戏会话期间灵活实现游戏技能,例如提供的扩展功能可用于实现冷却和使用消耗、玩家输入、使用动画蒙太奇的动画,以及对给予Actor的技能本身做出反应。

基本用法

将游戏性技能给予Actor的技能系统组件后,游戏性技能的基本执行生命期为:

  1. TryActivateAbility函数将调用CanActivateAbility,以确定该技能是否能够立即运行,如果可以,则立即运行。如果游戏需要在不实际执行某个技能的情况下,了解该技能能否执行,可以自行调用CanActivateAbility,以实现灰显或隐藏代表该技能的图标等。

  2. CallActivateAbility执行技能计划执行的游戏代码,并将由TryActivateAbility调用。如果不需要检查CanActivateAbility,它也可以被直接调用。

    • 用户需要使用技能的定制功能覆盖的主代码要么是名为ActivateAbility的C++函数,要么是名为Activate Ability的蓝图事件。

    • 与Actor和组件不同,游戏性技能不会使用“tick”函数完成主要工作,而是在激活过程中启动技能任务,异步完成大部分工作,然后连接代理(在C++中)以处理这些任务的输出,或者连接节点以输出执行引脚(在蓝图中)。

    • 如果从“激活”中调用CommitAbility函数,它将应用执行技能的消耗,例如从游戏性属性中减去资源(例如“魔法值”、“体力值”或游戏系统所用的任何其他资源)和应用冷却。

    • CancelAbility提供了取消技能的机制,不过技能的CanBeCanceled函数可以拒绝请求。与CommitAbility不同,该函数可供技能外调用者使用。成功的取消先播放给On Gameplay Ability Cancelled,然后通过标准代码路径结束技能,让技能可运行特殊的清理代码,否则取消时的行为将与自行结束时的行为不同。

  3. 技能必须调用EndAbility C++函数或End Ability节点,才能正常关闭。如果技能已取消,在取消过程中,UGameplayAbility代码会自动调用该函数。如果未能正常结束技能,将导致游戏性技能系统认为技能仍在运行,从而带来一些影响,例如禁止将来再使用该技能或任何被该技能阻止的技能。例如,如果游戏的“喝补血药剂”游戏性技能没有正常结束,那么在喝血量药剂时无法执行的操作(例如喝其他药剂、快跑、爬梯子等)此时也无法执行,因为游戏性技能系统会认为你还在喝药剂。

要了解如何在UE4项目中设置游戏性技能,请阅读动作角色扮演游戏中的游戏性技能NEW! 文档。

标记

游戏性标记 有助于确定游戏性技能之间的交互方式。每种技能都拥有一组标记,以可影响其行为的方式识别和分类技能,还有游戏性标记容器和游戏标记查询,用于支持与其他技能进行交互。

游戏性标记变量

目的

Cancel Abilities With Tag

如果任何已在执行的技能带有与执行此技能时提供的列表匹配的标记,则取消那些技能。

Block Abilities With Tag

在执行此技能时,阻止执行具有匹配标记的任何其他技能。

Activation Owned Tags

在执行此技能时,技能的所有者将被给予这组标记。

Activation Required Tags

只有激活的Actor或组件具有所有这些标记时,技能才会被激活。

Activation Blocked Tags

只有激活的Actor或组件没有任何这些标记时,技能才会被激活

Target Required Tags

只有目标Actor或组件具有所有这些标记时,技能才会被激活。

Target Blocked Tags

只有目标Actor或组件没有任何这些标记时,技能才会被激活。

复制

游戏性技能支持复制内蕴状态和游戏性事件 ,或关闭复制以节省网络带宽和缩短CPU周期。技能的 游戏性技能复制策略(Gameplay Ability Replication Policy) 可以设置为“是”或“否”,这控制着技能是否复制自身实例、更新状态或跨网络发送游戏性事件。对于复制技能的多人游戏,你可以选择复制的处理方式,这些选项被称为 游戏性网络执行策略(Gameplay Net Execution Policy)

  1. 本地预测:(Local Predicted:)此选项有助于在响应能力和准确性之间实现良好的平衡。在本地客户端发出命令后,技能将立即在客户端上运行,但服务器起着决定性作用,并且可以根据技能的实际影响来覆盖客户端。客户端实际上是从服务器请求执行“技能”的权限,但也在本地进行处理,就像服务器需要同意客户端对结果的看法一样。因为客户端在本地预测技能的行为,所以只要客户端的预测与服务器不矛盾,它就会非常顺利地运行且无滞后。

  2. 仅限本地:(Local Only:)客户端仅在本地运行技能。如果使用服务器的客户端是主机(在物理服务器计算机上播放)或者是在单人游戏中,尽管技能将在服务器上运行,也不会对服务器应用复制。这种情况不适用于专用服务器游戏,因为在专用服务器游戏中客户端永远不会在服务器计算机上运行。客户端通过该技能带来的任何影响都将受常规复制规则的约束,包括可能从服务器接收更正。

  3. 服务器启动:(Server Initiated:)在服务器上启动的技能将传播到客户端。从客户端的角度来看,这可以更准确地复制服务器上实际发生的情况,但使用技能的客户端会因缺少本地预测而发生延迟。虽然这种延迟非常短,但某些类型的技能(特别是在压力情况下快速执行的操作)将不会像在本地预测模式中那样顺畅。

  4. 仅限服务器:(Server Only:)“仅限服务器”技能将在服务器上运行,不会复制到客户端。受这些技能影响的任何变量都将像往常一样进行复制,这意味着服务器权威数据可能会受到技能的影响并将影响传递给客户端,尽管技能本身只在服务器上运行。

实例化策略

在执行游戏性技能时,通常会产生一个(技能类型的)新对象,用于跟踪正在进行的技能。由于在某些情况下可能会非常频繁地执行技能,例如在大逃杀、MOBA、MMO或RTS游戏中一百个或更多玩家与AI角色之间的战斗,可能会出现快速创建技能对象对性能产生负面影响的情况。为了解决这个问题,技能可以选择三种不同的实例化策略,以在效率和功能之间达到平衡。支持的三种实例化类型:

  • 按执行实例化:(Instanced per Execution:)每次技能运行时,都会产生技能对象的副本。这样做的优点是可以自由使用蓝图图形和成员变量,并且所有内容都将在执行开始时初始化为默认值。这是最简单的实例化策略,但该策略不能应用于频繁运行的技能。例如,MOBA中的“终极技能”可以使用该策略,因为两次执行之间存在较长的冷却时间(通常为60-90秒),并且只有少数几个角色(通常约为10个)使用这些技能。由计算机控制的“小兵”使用的基本攻击技能就不能使用该策略,因为可能同时存在数百个“小兵”,每个都可以频繁地发出基本攻击,从而导致快速创建(或者复制)新对象。

  • 按Actor实例化:(Instanced per Actor:)在技能首次执行时,每个Actor会生成该技能的一个实例,该对象会在以后的执行中重复使用。这就要求在两次技能执行之间清理成员变量,同时也使保存多个执行的信息成为可能。按Actor是较为理想的复制方法,因为技能具有可处理变量和RPC的复制对象,而不是浪费网络带宽和CPU时间,在每次运行时产生新对象。该策略适用于大规模的情况,因为大量使用技能的Actor(例如在大型战斗中)只会在第一次使用技能时产生对象。

  • 非实例化:(Non-Instanced:)这是所有类别中最高效的实例化策略。在运行时,技能不会生成任何对象,而是使用类默认对象 。但是,在高效的同时也伴随着一些限制。首先,该策略特别要求技能完全用C ++编写,因为没有对象实例就无法创建蓝图图形。你可以创建非实例化技能的蓝图类,但这些蓝图类只能用于更改已公开属性的默认值。此外,在执行技能期间,即使在本机C ++代码中,也不能更改成员变量,不能绑定代理,并且技能不能复制变量或处理RPC。该策略仅适用于不需要内部变量存储(尽管可以针对技能用户设置属性)并且不需要复制任何数据的技能。它尤其适合频繁运行且被许多角色使用的技能,例如大型RTS或MOBA作品中部队使用的基本攻击。

触发游戏性事件

游戏性事件(Gameplay Events) 是可以传递的数据结构,能够直接触发游戏性技能,无需通过正常通道,即可根据情境发送数据有效负载。常用的方法是调用Send Gameplay Event To Actor并提供实施IAbilitySystemInterface接口的Actor和游戏性事件所需的情境信息,但也可以直接在技能系统组件上调用Handle Gameplay Event。因为这不是调用游戏性技能的正常方式,所以技能可能需要的情境信息将通过FGameplayEventData数据结构传递。该结构是一种通用结构,不会针对任何特定的游戏性事件或技能进行扩展,但应该能够满足任何用例的要求。多态ContextHandle字段会根据需要提供其他信息。

当游戏事件触发游戏性技能时,游戏性技能不会通过激活技能代码路径运行,而是使用提供附加情境数据作为参数的“从事件激活技能”(Activate Ability From Event)。如果希望技能响应游戏事件,请务必处理此代码路径,同时还应注意,一旦在游戏性技能的蓝图中实施,“从事件激活技能”(Activate Ability From Event)将取代“激活技能”(Activate Ability),让所有激活流量通过自身。