UE5多人MOBA+GAS 25、创建数据表初始化属性,使用MMC计算伤害
用数据表初始化角色属性
在CGameplayAbilityTypes
添加新的结构体用作数据表
// 英雄基础属性结构体(用于数据表)
USTRUCT(BlueprintType)
struct FHeroBaseStats : public FTableRowBase
{GENERATED_BODY()
public:FHeroBaseStats();// 英雄类UPROPERTY(EditAnywhere)TSubclassOf<AActor> Class;// 力量UPROPERTY(EditAnywhere)float Strength;// 智力UPROPERTY(EditAnywhere)float Intelligence;// 力量成长率UPROPERTY(EditAnywhere)float StrengthGrowthRate;// 智力成长率UPROPERTY(EditAnywhere)float IntelligenceGrowthRate;// 基础最大生命UPROPERTY(EditAnywhere)float BaseMaxHealth;// 基础最大法力UPROPERTY(EditAnywhere)float BaseMaxMana;// 基础攻击力UPROPERTY(EditAnywhere)float BaseAttackDamage;// 基础护甲UPROPERTY(EditAnywhere)float BaseArmor;// 基础移动速度UPROPERTY(EditAnywhere)float BaseMoveSpeed;
};
创建数据表格填数值
UCLASS()
class UCAbilitySystemComponent : public UAbilitySystemComponent
{GENERATED_BODY()
public:UCAbilitySystemComponent();// 初始化基础属性void InitializeBaseAttributes();// 服务器初始化void ServerSideInit();
private:// 基础属性数据表UPROPERTY(EditDefaultsOnly, Category = "Base Stats")TObjectPtr<UDataTable> BaseStatDataTable;
void UCAbilitySystemComponent::InitializeBaseAttributes()
{if (!BaseStatDataTable || !GetOwner()){return;}const FHeroBaseStats* BaseStats = nullptr;for (const TPair<FName, uint8*>& DataPair : BaseStatDataTable->GetRowMap()){BaseStats = BaseStatDataTable->FindRow<FHeroBaseStats>(DataPair.Key, "");if (BaseStats && BaseStats->Class == GetOwner()->GetClass()){break; //找到后退出}}if (BaseStats){// 设置基础战斗属性SetNumericAttributeBase(UCAttributeSet::GetMaxHealthAttribute(), BaseStats->BaseMaxHealth); // 最大生命值SetNumericAttributeBase(UCAttributeSet::GetMaxManaAttribute(), BaseStats->BaseMaxMana); // 最大魔法值SetNumericAttributeBase(UCAttributeSet::GetAttackDamageAttribute(), BaseStats->BaseAttackDamage); // 攻击伤害SetNumericAttributeBase(UCAttributeSet::GetArmorAttribute(), BaseStats->BaseArmor); // 护甲值SetNumericAttributeBase(UCAttributeSet::GetMoveSpeedAttribute(), BaseStats->BaseMoveSpeed); // 移动速度// 设置角色成长属性SetNumericAttributeBase(UCHeroAttributeSet::GetStrengthAttribute(), BaseStats->Strength); // 力量SetNumericAttributeBase(UCHeroAttributeSet::GetStrengthGrowthRateAttribute(), BaseStats->StrengthGrowthRate); // 力量成长率SetNumericAttributeBase(UCHeroAttributeSet::GetIntelligenceAttribute(), BaseStats->Intelligence); // 智力SetNumericAttributeBase(UCHeroAttributeSet::GetIntelligenceGrowthRateAttribute(), BaseStats->IntelligenceGrowthRate); // 智力成长率}
}void UCAbilitySystemComponent::ServerSideInit()
{InitializeBaseAttributes();ApplyInitialEffects();GiveInitialAbilities();
}
基础角色中更改一下
void ACCharacter::ServerSideInit()
{// 设置当前角色作为Owner和Avatar,用于后续的能力和效果应用CAbilitySystemComponent->InitAbilityActorInfo(this, this);CAbilitySystemComponent->ServerSideInit();
}
把数据表格放入角色中
这里的初始化就可以删掉了
把属性上的速度与角色的速度绑定起来
CCharacter
#pragma region GAS组件相关
public:// 移动速度改变回调void MoveSpeedUpdatad(const FOnAttributeChangeData& Data);
void ACCharacter::BindGASChangeDelegates()
{if (CAbilitySystemComponent){CAbilitySystemComponent->RegisterGameplayTagEvent(TGameplayTags::Stats_Dead).AddUObject(this, &ACCharacter::DeathTagUpdated);CAbilitySystemComponent->RegisterGameplayTagEvent(TGameplayTags::Stats_Stun).AddUObject(this, &ACCharacter::StunTagUpdated);CAbilitySystemComponent->RegisterGameplayTagEvent(TGameplayTags::Stats_Aim).AddUObject(this, &ACCharacter::AimTagUpdated);CAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CAttributeSet->GetMoveSpeedAttribute()).AddUObject(this, &ACCharacter::MoveSpeedUpdatad);}
}
void ACCharacter::MoveSpeedUpdatad(const FOnAttributeChangeData& Data)
{GetCharacterMovement()->MaxWalkSpeed = Data.NewValue;
}
使用MMC计算伤害
MMC_BaseAttackDamage
创建后在GE添加这个计算类
// 幻雨喜欢小猫咪#pragma once#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "MMC_BaseAttackDamage.generated.h"/*** */
UCLASS()
class UMMC_BaseAttackDamage : public UGameplayModMagnitudeCalculation
{GENERATED_BODY()public:UMMC_BaseAttackDamage();virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
private:FGameplayEffectAttributeCaptureDefinition DamageCaptureDef;FGameplayEffectAttributeCaptureDefinition ArmorCaptureDef;
};
通过CalculateBaseMagnitude_Implementation
返回的值就是最终输出扣多少血的值
// 幻雨喜欢小猫咪#include "GAS/MMC/MMC_BaseAttackDamage.h"#include "GAS/Core/CAttributeSet.h"UMMC_BaseAttackDamage::UMMC_BaseAttackDamage()
{// 捕获伤害属性DamageCaptureDef.AttributeToCapture = UCAttributeSet::GetAttackDamageAttribute();// 属性来源指定为释放者DamageCaptureDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Source;// 捕获目标的护甲属性ArmorCaptureDef.AttributeToCapture = UCAttributeSet::GetArmorAttribute();ArmorCaptureDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Target;// 添加捕获属性RelevantAttributesToCapture.Add(DamageCaptureDef);RelevantAttributesToCapture.Add(ArmorCaptureDef);
}float UMMC_BaseAttackDamage::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{FAggregatorEvaluateParameters EvalParams;// 绑定源/目标标签EvalParams.SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();EvalParams.TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();float AttackDamage = 0.f;// 获取攻击力属性值(通过DamageCaptureDef定义的捕获规则)GetCapturedAttributeMagnitude(DamageCaptureDef, Spec, EvalParams, AttackDamage); // 获取源的属性值float Armor = 0.f;// 获取目标护甲属性值(通过ArmorCaptureDef定义的捕获规则)GetCapturedAttributeMagnitude(ArmorCaptureDef, Spec, EvalParams, Armor); // 获取目标的属性值// 计算最终伤害// 公式:Damage = AttackDamage * (1 - Armor / (Armor + 100))// 护甲减伤率 = Armor / (Armor + 100)float Damage = AttackDamage * (1 - Armor / (Armor + 100));return -Damage;
}