找回密码
 立即注册
查看: 218|回复: 0

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

[复制链接]
发表于 2022-12-18 18:13 | 显示全部楼层 |阅读模式
原文:

兼容联网环境的 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 就好,是同步的。

相关链接

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 14:25 , Processed in 0.090849 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表