当前位置: 首页 > news >正文

UE5多人MOBA+GAS 27、死亡被动(用于作为击杀奖励,爆金币和是增加经验)

文章目录

  • 添加死亡被动
  • 激活死亡被动技能
    • MMC做法
    • ECC做法
  • 寻找奖励目标
  • 奖励的计算与发放
  • 完整死亡被动


添加一个标签用来区分该Actor是否是英雄单位

CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Role_Hero)
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Role_Hero, "Role.Hero", "英雄角色")

添加死亡被动

继承C技能添加一个死亡被动技能
在这里插入图片描述

// 幻雨喜欢小猫咪#pragma once#include "CoreMinimal.h"
#include "GAS/Core/CGameplayAbility.h"
#include "GAP_Dead.generated.h"/*** 死亡能力类* 负责角色死亡时的奖励分配(经验、金币等)*/
UCLASS()
class CRUNCH_API UGAP_Dead : public UCGameplayAbility
{GENERATED_BODY()
public:UGAP_Dead();virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;};
// 幻雨喜欢小猫咪#include "GAS/Abilities/GAP_Dead.h"#include "GAS/Core/TGameplayTags.h"UGAP_Dead::UGAP_Dead()
{// 设置网络执行策略为仅在服务器端执行NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerOnly;// 创建一个新触发数据对象FAbilityTriggerData TriggerData;// 设置触发数据的触发源为游戏事件TriggerData.TriggerSource = EGameplayAbilityTriggerSource::GameplayEvent;TriggerData.TriggerTag = TGameplayTags::Stats_Dead;AbilityTriggers.Add(TriggerData);// 死亡去除眩晕状态ActivationBlockedTags.RemoveTag(TGameplayTags::Stats_Stun);
}void UGAP_Dead::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{if (K2_HasAuthority()){AActor* Killer = TriggerEventData->ContextHandle.GetEffectCauser();if (!Killer){UE_LOG(LogTemp, Warning, TEXT("Killer is null"))}else{UE_LOG(LogTemp, Warning, TEXT("Killer is : %s"), *Killer->GetName())}}
}

激活死亡被动技能

ASC中添加被动技能,以及在死亡的时候激活死亡被动技能(如果使用MMC的话就在这里激活技能使用ECC的话获取不到敌人)
这是直接用GE来计算扣血的操作
请添加图片描述
ECC的扣血触发的话就会无法获取角色
在这里插入图片描述

	// 被动技能UPROPERTY(EditDefaultsOnly, Category = "Gameplay Ability")TArray<TSubclassOf<UGameplayAbility>> PassiveAbilities;
void UCAbilitySystemComponent::GiveInitialAbilities()
{// 检查当前组件是否拥有拥有者,并且拥有者是否具有网络权限(权威性) if (!GetOwner() || !GetOwner()->HasAuthority()) return;for (const TPair<ECAbilityInputID,TSubclassOf<UGameplayAbility>>& AbilityPair : BasicAbilities){// 赋予技能 等级为 1GiveAbility(FGameplayAbilitySpec(AbilityPair.Value, 1, static_cast<int32>(AbilityPair.Key), nullptr));}for (const TPair<ECAbilityInputID,TSubclassOf<UGameplayAbility>>& AbilityPair : Abilities){GiveAbility(FGameplayAbilitySpec(AbilityPair.Value, 0, static_cast<int32>(AbilityPair.Key), nullptr));}for (const TSubclassOf<UGameplayAbility>& PassiveAbility : PassiveAbilities){GiveAbility(FGameplayAbilitySpec(PassiveAbility, 1, -1, nullptr));}
}

在这里插入图片描述

MMC做法

void UCAbilitySystemComponent::HealthUpdated(const FOnAttributeChangeData& ChangeData)
{if (!GetOwner() || !GetOwner()->HasAuthority()) return;// 获取当前最大生命值bool bFound = false;float MaxHealth = GetGameplayAttributeValue(UCAttributeSet::GetMaxHealthAttribute(), bFound);// 如果生命值达到最大值,添加生命值已满标签if (bFound && ChangeData.NewValue >= MaxHealth){if (!HasMatchingGameplayTag(TGameplayTags::Stats_Health_Full)){// 仅本地会添加标签AddLooseGameplayTag(TGameplayTags::Stats_Health_Full);}}else{// 移除生命值已满标签RemoveLooseGameplayTag(TGameplayTags::Stats_Health_Full);}if (ChangeData.NewValue <= 0.0f){if (!HasMatchingGameplayTag(TGameplayTags::Stats_Health_Empty)){// 本地添加生命值清零标签AddLooseGameplayTag(TGameplayTags::Stats_Health_Empty);// 角色死亡if (DeathEffect){AuthApplyGameplayEffect(DeathEffect);}// 创建需要传给死亡被动技能的事件数据FGameplayEventData DeadAbilityEventData;if (ChangeData.GEModData){DeadAbilityEventData.ContextHandle = ChangeData.GEModData->EffectSpec.GetContext();}else{UE_LOG(LogTemp, Error, TEXT("ChangeData.GEModData is null"))}UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(GetOwner(), TGameplayTags::Stats_Dead, DeadAbilityEventData);}}else{RemoveLooseGameplayTag(TGameplayTags::Stats_Health_Empty);}
}

ECC做法

MMC那种在ASC里面获取的GEModData和属性里获取的const FGameplayEffectModCallbackData& Data是同一种数据类型
在这里插入图片描述

在属性里伤害接收这里判断生命是否小于等于0
在这里插入图片描述
两种方法都可以

void UCAttributeSet::OnDeadAbility(const FGameplayEffectModCallbackData& Data)
{FGameplayEventData DeadAbilityEventData;if (AActor* TargetActor = Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent()->AbilityActorInfo->AvatarActor.Get()){UE_LOG(LogTemp, Warning, TEXT("Dead:%s"), *GetOwningActor()->GetName())DeadAbilityEventData.Target = TargetActor;DeadAbilityEventData.ContextHandle = Data.EffectSpec.GetContext();}UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(GetOwningActor(), TGameplayTags::Stats_Dead, DeadAbilityEventData);
}
void UGAP_Dead::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{if (K2_HasAuthority()){// MMC 获取// AActor* Killer = TriggerEventData->ContextHandle.GetEffectCauser();// ECC 获取AActor* Killer = nullptr;if (TriggerEventData->ContextHandle.GetOriginalInstigatorAbilitySystemComponent()->AbilityActorInfo->AvatarActor.Get()){Killer = TriggerEventData->ContextHandle.GetOriginalInstigatorAbilitySystemComponent()->AbilityActorInfo->AvatarActor.Get();UE_LOG(LogTemp, Warning, TEXT("TriggerEventData->ContextHandle.GetOriginalInstigatorAbilitySystemComponent()->AbilityActorInfo->AvatarActor.Get(): %s"), *Killer->GetName())}if (TriggerEventData->Target){Killer = static_cast<AActor*>(TriggerEventData->Target);UE_LOG(LogTemp, Warning, TEXT("TriggerEventData->Target: %s"), *Killer->GetName())}if (!Killer){UE_LOG(LogTemp, Warning, TEXT("Killer is null"))}else{UE_LOG(LogTemp, Warning, TEXT("Killer is : %s"), *Killer->GetName())}}
}

在这里插入图片描述
在这里插入图片描述

寻找奖励目标

设置一个范围的检测,寻找击杀者的阵容的英雄单位,因此在CAbilitySystemStatics中添加一个函数来判断是否为英雄

	// 判断是否为英雄static bool IsHero(const AActor* ActorToCheck);
bool UCAbilitySystemStatics::IsHero(const AActor* ActorToCheck)
{const IAbilitySystemInterface* ActorISA = Cast<IAbilitySystemInterface>(ActorToCheck);if (ActorISA){UAbilitySystemComponent* ActorASC = ActorISA->GetAbilitySystemComponent();if (ActorASC){return ActorASC->HasMatchingGameplayTag(TGameplayTags::Role_Hero);}}return false;
}
private:// 奖励分配的范围,在该范围内的队友可获得奖励UPROPERTY(EditDefaultsOnly, Category = "Reward")float RewardRange = 1000.f;// 获取奖励目标(如附近的队友等)TArray<AActor*> GetRewardTargets() const;
// 幻雨喜欢小猫咪#include "GAS/Abilities/GAP_Dead.h"#include "AbilitySystemComponent.h"
#include "Engine/OverlapResult.h"
#include "GAS/Core/CAbilitySystemStatics.h"
#include "GAS/Core/TGameplayTags.h"UGAP_Dead::UGAP_Dead()
{// 设置网络执行策略为仅在服务器端执行NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerOnly;// 创建一个新触发数据对象FAbilityTriggerData TriggerData;// 设置触发数据的触发源为游戏事件TriggerData.TriggerSource = EGameplayAbilityTriggerSource::GameplayEvent;TriggerData.TriggerTag = TGameplayTags::Stats_Dead;AbilityTriggers.Add(TriggerData);// 死亡去除眩晕状态ActivationBlockedTags.RemoveTag(TGameplayTags::Stats_Stun);
}void UGAP_Dead::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{if (K2_HasAuthority()){// MMC 获取// AActor* Killer = TriggerEventData->ContextHandle.GetEffectCauser();// ECC 获取AActor* Killer = nullptr;if (TriggerEventData->Target){Killer = static_cast<AActor*>(TriggerEventData->Target);UE_LOG(LogTemp, Warning, TEXT("TriggerEventData->Target: %s"), *Killer->GetName())}if (!Killer){UE_LOG(LogTemp, Warning, TEXT("Killer is null"))K2_EndAbility();return;}TArray<AActor*> RewardTargets = GetRewardTargets();for (const AActor* RewardTarget : RewardTargets){UE_LOG(LogTemp, Warning, TEXT("Find Reward Target: %s"), *RewardTarget->GetName());}K2_EndAbility();}
}TArray<AActor*> UGAP_Dead::GetRewardTargets() const
{TSet<AActor*> OutActors;AActor* AvatarActor = GetAvatarActorFromActorInfo();if (!AvatarActor || !GetWorld()){return OutActors.Array();}// 配置碰撞检测参数FCollisionObjectQueryParams ObjectQueryParams;ObjectQueryParams.AddObjectTypesToQuery(ECC_Pawn);FCollisionShape CollisionShape;CollisionShape.SetSphere(RewardRange);  // 使用奖励范围作为检测半径TArray<FOverlapResult> OverlapResults;// 检测碰撞if (GetWorld()->OverlapMultiByObjectType(OverlapResults, AvatarActor->GetActorLocation(), FQuat::Identity, ObjectQueryParams, CollisionShape)){for (const FOverlapResult& OverlapResult : OverlapResults){// 获取团队接口,给死亡目标的敌对单位提供奖励const IGenericTeamAgentInterface* TeamInterface =  Cast<IGenericTeamAgentInterface>(OverlapResult.GetActor());// 过滤非敌对单位if (!TeamInterface || TeamInterface->GetTeamAttitudeTowards(*AvatarActor) != ETeamAttitude::Hostile){continue;}// 判断是否为英雄单位if (!UCAbilitySystemStatics::IsHero(OverlapResult.GetActor())){continue;}// 添加到奖励目标集合OutActors.Add(OverlapResult.GetActor());}}return OutActors.Array();
}

创建一个GE用来将英雄的Tag赋值给英雄
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

奖励的计算与发放

添加两个标签用于GE调用数值

	// 经验CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(AttributeSet_Experience)// 金币CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(AttributeSet_Gold)
	UE_DEFINE_GAMEPLAY_TAG_COMMENT(AttributeSet_Experience, "AttributeSet.Experience", "经验值")UE_DEFINE_GAMEPLAY_TAG_COMMENT(AttributeSet_Gold, "AttributeSet.Gold", "金币")

给死亡被动添加一些属性用于分配奖励以及发放奖励的GE

private:// 奖励分配的范围,在该范围内的队友可获得奖励UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="奖励范围"))float RewardRange = 1000.f;// 基础经验奖励UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="基础经验奖励"))float BaseExperienceReward = 200.f;// 基础金币奖励UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="基础金币奖励"))float BaseGoldReward = 200.f;// 额外经验奖励系数(根据目标经验值加成)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="经验奖励系数(每单位经验)"))float ExperienceRewardPerExperience = 0.1f;// 额外金币奖励系数(根据目标经验值加成)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="金币奖励系数(每单位经验)"))float GoldRewardPerExperience = 0.05f;// 击杀者奖励占比(击杀者获得的奖励比例,其余分配给队友)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="击杀者奖励比例(0-1)"))float KillerRewardPortion = 0.5f;// 获取奖励目标(如附近的队友等)TArray<AActor*> GetRewardTargets() const;// 奖励GE(用于发放经验、金币等)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="奖励效果(GE类)"))TSubclassOf<UGameplayEffect> RewardEffect;
void UGAP_Dead::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{if (K2_HasAuthority()){// MMC 获取// AActor* Killer = TriggerEventData->ContextHandle.GetEffectCauser();// ECC 获取AActor* Killer = nullptr;if (TriggerEventData->Target){Killer = static_cast<AActor*>(TriggerEventData->Target);UE_LOG(LogTemp, Warning, TEXT("TriggerEventData->Target: %s"), *Killer->GetName())}// 击杀者不存在或者击杀者为非英雄单位if (!Killer || !UCAbilitySystemStatics::IsHero(Killer)){Killer = nullptr;}// 获取需要奖励的目标TArray<AActor*> RewardTargets = GetRewardTargets();// 如果没有奖励目标又没有击杀者直接结束技能不需要奖励if (RewardTargets.Num() == 0 && !Killer){K2_EndAbility();return;}// 击杀者存在并且不在奖励目标中,将击杀者添加进去if (Killer && !RewardTargets.Contains(Killer)){RewardTargets.Add(Killer);}bool bFound = false;// 获取角色当前经验属性值float SelfExperience = GetAbilitySystemComponentFromActorInfo_Ensured()->GetGameplayAttributeValue(UCHeroAttributeSet::GetExperienceAttribute(), bFound);// 计算总奖励(基础奖励+基于经验的奖励)float TotalExperienceReward = BaseExperienceReward + ExperienceRewardPerExperience * SelfExperience;float TotalGoldReward = BaseGoldReward + GoldRewardPerExperience * SelfExperience;// 判断是否有击杀的英雄单位,给他分大头if (Killer){float KillerExperienceReward = TotalExperienceReward * KillerRewardPortion;float KillerGoldReward = TotalGoldReward * KillerRewardPortion;// 创建击杀者奖励效果FGameplayEffectSpecHandle EffectSpecHandle = MakeOutgoingGameplayEffectSpec(RewardEffect);// 设置GE上面的属性值EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Experience, KillerExperienceReward);EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Gold, KillerGoldReward);// 对击杀者应用奖励效果K2_ApplyGameplayEffectSpecToTarget(EffectSpecHandle, UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActor(Killer));// 从总奖励中扣除击杀者部分TotalExperienceReward -= KillerExperienceReward;TotalGoldReward -= KillerGoldReward;}// 把剩余的奖励平均分配给没有k到头的英雄单位(k到的也能多吃一口)float ExperiencePerTarget = TotalExperienceReward / RewardTargets.Num();float GoldPerTarget = TotalGoldReward / RewardTargets.Num();// 创建群体奖励效果FGameplayEffectSpecHandle EffectSpecHandle = MakeOutgoingGameplayEffectSpec(RewardEffect);// 设置GE上面的属性值EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Experience, ExperiencePerTarget);EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Gold, GoldPerTarget);// 对所有奖励目标应用奖励K2_ApplyGameplayEffectSpecToTarget(EffectSpecHandle, UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActorArray(RewardTargets, true));K2_EndAbility();}
}

创建一个GE用于给奖励
在这里插入图片描述
配置到死亡被动中
在这里插入图片描述
添加两个属性监听看一下效果
在这里插入图片描述

在这里插入图片描述
击杀者拿一半,然后再两个人再平分剩下的一半,没错
在这里插入图片描述

完整死亡被动

// 幻雨喜欢小猫咪#pragma once#include "CoreMinimal.h"
#include "GAS/Core/CGameplayAbility.h"
#include "GAP_Dead.generated.h"/*** 死亡能力类* 负责角色死亡时的奖励分配(经验、金币等)*/
UCLASS()
class CRUNCH_API UGAP_Dead : public UCGameplayAbility
{GENERATED_BODY()
public:UGAP_Dead();virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;private:// 奖励分配的范围,在该范围内的队友可获得奖励UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="奖励范围"))float RewardRange = 1000.f;// 基础经验奖励UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="基础经验奖励"))float BaseExperienceReward = 200.f;// 基础金币奖励UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="基础金币奖励"))float BaseGoldReward = 200.f;// 额外经验奖励系数(根据目标经验值加成)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="经验奖励系数(每单位经验)"))float ExperienceRewardPerExperience = 0.1f;// 额外金币奖励系数(根据目标经验值加成)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="金币奖励系数(每单位经验)"))float GoldRewardPerExperience = 0.05f;// 击杀者奖励占比(击杀者获得的奖励比例,其余分配给队友)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="击杀者奖励比例(0-1)"))float KillerRewardPortion = 0.5f;// 获取奖励目标(如附近的队友等)TArray<AActor*> GetRewardTargets() const;// 奖励GE(用于发放经验、金币等)UPROPERTY(EditDefaultsOnly, Category = "Reward", meta=(DisplayName="奖励效果(GE类)"))TSubclassOf<UGameplayEffect> RewardEffect;
};
// 幻雨喜欢小猫咪#include "GAS/Abilities/GAP_Dead.h"#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"
#include "Engine/OverlapResult.h"
#include "GAS/Core/CAbilitySystemStatics.h"
#include "GAS/Core/CHeroAttributeSet.h"
#include "GAS/Core/TGameplayTags.h"UGAP_Dead::UGAP_Dead()
{// 设置网络执行策略为仅在服务器端执行NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerOnly;// 创建一个新触发数据对象FAbilityTriggerData TriggerData;// 设置触发数据的触发源为游戏事件TriggerData.TriggerSource = EGameplayAbilityTriggerSource::GameplayEvent;TriggerData.TriggerTag = TGameplayTags::Stats_Dead;AbilityTriggers.Add(TriggerData);// 死亡去除眩晕状态ActivationBlockedTags.RemoveTag(TGameplayTags::Stats_Stun);
}void UGAP_Dead::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{if (K2_HasAuthority()){// MMC 获取// AActor* Killer = TriggerEventData->ContextHandle.GetEffectCauser();// ECC 获取AActor* Killer = nullptr;if (TriggerEventData->Target){Killer = static_cast<AActor*>(TriggerEventData->Target);UE_LOG(LogTemp, Warning, TEXT("TriggerEventData->Target: %s"), *Killer->GetName())}// 击杀者不存在或者击杀者为非英雄单位if (!Killer || !UCAbilitySystemStatics::IsHero(Killer)){Killer = nullptr;}// 获取需要奖励的目标TArray<AActor*> RewardTargets = GetRewardTargets();// 如果没有奖励目标又没有击杀者直接结束技能不需要奖励if (RewardTargets.Num() == 0 && !Killer){K2_EndAbility();return;}// 击杀者存在并且不在奖励目标中,将击杀者添加进去if (Killer && !RewardTargets.Contains(Killer)){RewardTargets.Add(Killer);}bool bFound = false;// 获取角色当前经验属性值float SelfExperience = GetAbilitySystemComponentFromActorInfo_Ensured()->GetGameplayAttributeValue(UCHeroAttributeSet::GetExperienceAttribute(), bFound);// 计算总奖励(基础奖励+基于经验的奖励)float TotalExperienceReward = BaseExperienceReward + ExperienceRewardPerExperience * SelfExperience;float TotalGoldReward = BaseGoldReward + GoldRewardPerExperience * SelfExperience;// 判断是否有击杀的英雄单位,给他分大头if (Killer){float KillerExperienceReward = TotalExperienceReward * KillerRewardPortion;float KillerGoldReward = TotalGoldReward * KillerRewardPortion;UE_LOG(LogTemp, Warning, TEXT("击杀者经验奖励:%f"), KillerExperienceReward)// 创建击杀者奖励效果FGameplayEffectSpecHandle EffectSpecHandle = MakeOutgoingGameplayEffectSpec(RewardEffect);// 设置GE上面的属性值EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Experience, KillerExperienceReward);EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Gold, KillerGoldReward);// 对击杀者应用奖励效果K2_ApplyGameplayEffectSpecToTarget(EffectSpecHandle, UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActor(Killer));// 从总奖励中扣除击杀者部分TotalExperienceReward -= KillerExperienceReward;TotalGoldReward -= KillerGoldReward;}// 把剩余的奖励平均分配给没有k到头的英雄单位float ExperiencePerTarget = TotalExperienceReward / RewardTargets.Num();float GoldPerTarget = TotalGoldReward / RewardTargets.Num();UE_LOG(LogTemp, Warning, TEXT("数组里面多少人%d"), RewardTargets.Num())UE_LOG(LogTemp, Warning, TEXT("平均经验奖励:%f"), ExperiencePerTarget)// 创建群体奖励效果FGameplayEffectSpecHandle EffectSpecHandle = MakeOutgoingGameplayEffectSpec(RewardEffect);// 设置GE上面的属性值EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Experience, ExperiencePerTarget);EffectSpecHandle.Data->SetSetByCallerMagnitude(TGameplayTags::AttributeSet_Gold, GoldPerTarget);// 对所有奖励目标应用奖励K2_ApplyGameplayEffectSpecToTarget(EffectSpecHandle, UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActorArray(RewardTargets, true));K2_EndAbility();}
}TArray<AActor*> UGAP_Dead::GetRewardTargets() const
{TSet<AActor*> OutActors;AActor* AvatarActor = GetAvatarActorFromActorInfo();if (!AvatarActor || !GetWorld()){return OutActors.Array();}// 配置碰撞检测参数FCollisionObjectQueryParams ObjectQueryParams;ObjectQueryParams.AddObjectTypesToQuery(ECC_Pawn);FCollisionShape CollisionShape;CollisionShape.SetSphere(RewardRange);  // 使用奖励范围作为检测半径TArray<FOverlapResult> OverlapResults;// 检测碰撞if (GetWorld()->OverlapMultiByObjectType(OverlapResults, AvatarActor->GetActorLocation(), FQuat::Identity, ObjectQueryParams, CollisionShape)){for (const FOverlapResult& OverlapResult : OverlapResults){// 获取团队接口,给死亡目标的敌对单位提供奖励const IGenericTeamAgentInterface* TeamInterface =  Cast<IGenericTeamAgentInterface>(OverlapResult.GetActor());// 过滤非敌对单位if (!TeamInterface || TeamInterface->GetTeamAttitudeTowards(*AvatarActor) != ETeamAttitude::Hostile){continue;}// 判断是否为英雄单位if (!UCAbilitySystemStatics::IsHero(OverlapResult.GetActor())){continue;}// 添加到奖励目标集合OutActors.Add(OverlapResult.GetActor());}}return OutActors.Array();
}
http://www.dtcms.com/a/290362.html

相关文章:

  • RPA与AI:从自动化到智能化的企业转型之路
  • AWS Certified Cloud Practitioner 认证考试 测试题与解析
  • 用Java 代码实现一个简单的负载均衡逻辑
  • 电子数据取证领域的双轮驱动——手工分析 vs 自动化分析
  • Web开发:ABP框架12——中间件Middleware的创建和使用
  • 轨迹优化 | 基于边界中间值问题(BIVP)的路径平滑求解器(附C++/Python仿真)
  • Python自然语言处理实战:spaCy从入门到进阶的工业级应用指南
  • 《C++》范围 for 循环,空指针nullptr
  • 【iOS】多界面传值(五大传值方式)
  • PHP高级进阶:突破编程边界,开启技术新征程
  • GaussDB alter table的用法
  • Charles 抓包工具中文版完整指南 提升 API 调试与性能调优
  • Netty实现单通道并发读写,即多路复用
  • 神经网络——线性层
  • 混合遗传粒子群算法在光伏系统MPPT中的应用研究
  • imx6ull-系统移植篇15——U-Boot 图形化配置(下)
  • 蚂蚁数科AI数据产业基地正式投产,携手苏州推进AI产业落地
  • 使用Python绘制专业柱状图:Matplotlib完全指南
  • 《Linux服务与安全管理》| 安装拼音输入法
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页布局实现
  • “hidden act“:“gelu“在bert中作用
  • 经典神经网络(vgg resnet googlenet)
  • 家庭网络怎么进行公网IP获取,及内网端口映射外网访问配置,附无公网IP提供互联网连接方案
  • 03-虚幻引擎蓝图类的各父类作用讲解
  • el-table固定高度,数据多出现滚动条,表头和内容对不齐
  • Eltable tree形式,序号列实现左对齐,并且每下一层都跟上一层的错位距离拉大
  • 深入解析Hadoop MapReduce Shuffle过程:从环形缓冲区溢写到Sort与Merge源码
  • VMware Workstation Pro克隆虚拟机导致网络异常解决方法
  • 深度学习 pytorch图像分类(详细版)
  • 【设计模式】观察者模式 (发布-订阅模式,模型-视图模式,源-监听器模式,从属者模式)