兼容联网环境的 Unreal 战斗攻受击全流程使用实践总结

Viewed 10

原文:

兼容联网环境的 Unreal 战斗攻受击全流程使用实践总结

前言

背景

  • 根据 GAS 官方教程和工程 GASDocumentation ,参考已有技能和逻辑,在新工程中搭建了联网环境,并添加了自己的技能和相关逻辑,测试通过。

目的

  • 记录
  • 记录一种可行的、较为标准的、官方推荐的、支持联网和单机的技能攻受击流程,包括主动技能、被动技能、技能 Cost、技能 Cooldown、攻击动作、攻击效果、受击动作、受击效果、掉血扣蓝等一般的战斗技能流程中的通用表现或逻辑。
  • 分享
  • 网上有较多 GAS 的教程,但大部分是单机下的,对于联网环境,不一定适用。本文基于验证过的网络环境(DS、P2P、Standalone均测试过),会特别记录下一些关键配置和流程。

说明

  • 本文主要参考 GAS 官方工程 GASDocumentation 及网络和官方的文档,虽为验证过的流程,但亦不代表这是标准联网开发的战斗流程,更不是唯一正确实践路线,也不是最佳路线。
  • 本文不会讨论研究 GAS 底层原理乃至概念,也不会深入讨论网络同步,只会从实战使用角度对全流程做说明,尽量让初学者在初步了解了GAS相关概念之后能系统地跑起来一个自己的技能。

效果


https://www.zhihu.com/video/1579965830376374273
全流程

全流程详细说明图

解释说明

  • 初始化
  • UAbilitySystemComponent::InitAbilityActorInfo
  • ASQCharacterBase::InitializeAttributes
  • 初始化血量、等级、血量回复速度等初始 GE
  • 通过 UAbilitySystemComponent::MakeOutgoingSpec 创建 FGameplayEffectSpecHandle
  • 再通过 UAbilitySystemComponent::ApplyGameplayEffectSpecToTarget 赋予目标
  • SetHealth(GetMaxHealth())
  • 设置初始属性,如让血量为最大值
  • 实际调用的是 USQAttributeSetBase 里
  • 通过 ATTRIBUTE_ACCESSORS 定义的 Health 等属性的 Set
  • UAbilitySystemComponent::GetGameplayAttributeValueChangeDelegate;
  • 监听属性如HP等的变化,
  • 方便后文处理血条等和HUD等的表现。
  • ASQCharacterBase::AddStartupEffects
  • 添加当前属性如HP等的初始GE
  • 实现方式跟上方的 InitializeAttributes 一样
  • UAbilitySystemComponent::GiveAbility
  • 赋予技能
  • 所有相关技能都要先 GiveAbility (不是 ActivateAbility )

  • 可以在 ASQCharacterBase 中把所有技能初始化

  • GiveAbility 时可以指定让技能与输入绑定

  • 攻击

  • ActivateAbility
  • 技能通过初始化时绑定的按键等输入主动触发
  • 也可以被动触发,见后文
  • CommitAbility
  • 判断校验,触发 GA 上配置的 Cost和Cooldown GE
  • 扣除对应的蓝,并让技能处于 CD
  • CreatePlayMontageAndWaitProxy
  • 播放攻击动画
  • BP和C++的接口略有不同,但底层一致
  • 如为C++,还需调用:
  • UAbilityTask_PlayMontageAndWait::Activate
  • SpawnActor
  • BP或C++生成带碰撞的子弹或攻击物
  • K2_EndAbility()
  • 结束攻击GA
  • BP中为 EndAbility
  • 受击触发
  • OnComponentBeginOverlap
  • (以子弹攻击为例)子弹击中目标
  • HasAuthority
  • 先判断是否有权限
  • UAbilitySystemComponent::ApplyGameplayEffectSpecToSelf
  • 对目标施加伤害GE和其它GE(如BUFF等)
  • 表现:血条更新
  • UAbilitySystemComponent::GetGameplayAttributeValueChangeDelegate
  • 在角色 BeginPlay 时监听属性变化
  • UIFloatingStatusBar->SetHealthPercentage(GetHealth() / GetMaxHealth());
  • 在收到属性变化的通知时,让血条等更新
  • 伤害掉血
  • UGameplayEffectExecutionCalculation:Execute
  • 伤害GE配置的 Execution GE 执行
  • Execute_Implementation;
  • 在执行回调中写逻辑
  • FGameplayEffectCustomExecutionParameters::AttemptCalculateCapturedAttributeMagnitude;
  • FGameplayEffectSpec::GetSetByCallerMagnitude;
  • 获取防御和伤害
  • FGameplayEffectCustomExecutionOutput::AddOutputModifier;
  • 施加属性变化
  • 收到属性变化的处理
  • USQAttributeSetBase::PostGameplayEffectExecute
  • Data.EvaluatedData.Attribute == GetDamageAttribute()
  • 根据属性标志来采取对应措施
  • Data.Target.AbilityActorInfo->AvatarActor.Get()
  • 拿到目标
  • 让目标播放受击动画
  • PlayHitReact
  • 这个方法必须是可靠广播
  • UFUNCTION(NetMulticast, Reliable, WithValidation)
  • PlayHitReact_Implementation;
  • 目标收到受击广播
  • UAbilitySystemBlueprintLibrary::SendGameplayEventToActor
  • 通过 GameplayEvent 来触发受击 GA (配置方式见说明)
  • 受击GA:
  • 播放受击动画(参考攻击)
  • UGameplayAbility::BP_ApplyGameplayEffectToOwner
  • 给目标添加受击GE
  • 受击GE配置受击特效GC(配置方式见说明)
  • 受击GC在GE触发时执行其 OnActive 等,在其中生成特效等
  • 血量等属性变化
  • USQAttributeSetBase Healtht
  • 属性必须是同步的,有配置变化回调
  • UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_Health)
  • OnRep_Health;
  • 收到属性变化
  • 通过 GAMEPLAYATTRIBUTE_REPNOTIFY(USQAttributeSetBase, Health, OldHealth) 来触发属性调整 FActiveGameplayEffectsContainer::SetBaseAttributeValueFromReplication
  • 更深入的底层此处略

问题答疑

  • 关于联网下被动技能的配置和触发
  • 对于被动技能 GA, 首先配置其 Trigger Tag 为受击 Tag
  • 然后选择 Trigger Source 为 Gameplay Event

  • 【特别注意】在 USQAttributeSetBase::PostGameplayEffectExecute 回调中,调用受击目标角色身上的 Reliable 方法 TargetCharacter->PlayHitReact 。

  • 在 PlayHitReact 的网络回调 PlayHitReact_Implementation 中,调用 UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(this, HitTag, FGameplayEventData()) 去触发目标身上的被动 GA 。
  • 如是才能让技能成功执行,动作成功播放。否则被动技能可能不会执行,或执行之后没效果。
  • 关于主动技能无法再次触发
  • 查看其是否配置了自身被自身技能 tag block,且其 cooldown 里是不是配置了 grade 自身的 skill tag
  • 关于伤害很小的子弹类技能把敌方秒杀了
  • 施加伤害GE是否是在子弹的碰撞逻辑中?如果是的话,打日志或debug一下看看是否在子弹销毁前有重复执行伤害GE施加。
  • 关于 UProjectileMovementComponent 生成的子弹不朝向目标飞行?
  • UProjectileMovementComponent 的 Velocity 3个值全部重置为0。
  • 关于参考 GASDocumentation 做的子弹能生成但是不产生伤害。
  • 如果子弹的伤害逻辑也是参考的 GASDocumentation ,则检查 SpawnActor时候 Instigator 要设置为技能发送者,而不是技能受击者。因为其逻辑中会判断 Instigator 决定是否产生伤害。
  • 关于 GC 无效果
  • 对应GE : DurationPolicy 必须配置为 has duration , magnitude attribute 设置 calculationtype 为 scalable float,值不为 0 , gameplay cues 里配置对应的 gameplay cue tags
  • C++ 中 WaitTargetData 不响应确认按键
  • C++中的 AbilityTask 需要手动调用ReadyForActivation(), BeginSpawningActor(), 和 FinishSpawningActor()。
  • BeginSpawningActor 会生成一个 actor,传给 FinishSpawningActor 就好,是同步的。

相关链接

GAS 官方文档

**声明:**本文来自公众号:GameDevLearning,转载请附上原文链接及本声明。

0 Answers