5.6 KiB
DataAsset与UObject
数据资产的巨大优势在于,你可以将它们设置为自动在引擎中注册,所以每次你添加一个新的数据资产时,引擎都会自动将其添加到一个列表中。因此,如果你的武器是数据资产,当你在游戏中添加一个新的武器时,它就会自动添加到一个你可以搜索的列表中,所以你不需要每次添加一个新的武器时在你的代码中手动添加绑定。
如果不需要这种类型的东西,把它变成数据资产就没有什么好处。
附魔
附魔分为临时附魔与永久附魔。临时附魔以Buffer的方式存在,其Handle存储在角色类中。永久附魔应用后的Handle则存储在所依附的物品类(武器或者身上的其他装备)中,用于解除装备后去除GE。
存在问题
- 如果武器存在属性,附魔也存在属性,那伤害该如何计算?
宝石(镶嵌物)
镶嵌在有限的武器槽中,增加角色属性或者改变武器(攻击)属性。
实现方式
在创建新的 Inlay 物品类,里面存储GameplayEffect用于调整角色属性与武器(攻击)属性。应用后的Handle存储在所依附的物品类(武器或者身上的其他装备)中,用于解除装备后去除GE。
武器的镶嵌物与附魔的初始信息存储在DataAsset中,而玩家runtime与存档信息则通过实例化的URPGWeaponItem来存储。WeaponActor保存对应的GEHandle,数据全都是临时性的,实现对应的方法。
GASDocument的武器数值实现
- 在物品上使用原始数值变量(推荐)
- 在物品类上使用独立的AttributeSet
- 在物品类上使用独立的ASC
具体可以参考GASShooter项目。不使用AttributeSet,直接将数值存在在武器类或者GameplayABility中内。
运行时添加与移除属性级
//On weapon add to inventory:
AbilitySystemComponent->SpawnedAttributes.AddUnique(WeaponAttributeSetPointer);
AbilitySystemComponent->ForceReplication();
//On weapon remove from inventory:
AbilitySystemComponent->SpawnedAttributes.Remove(WeaponAttributeSetPointer);
AbilitySystemComponent->ForceReplication();
各个方案的好处与坏处
使用原始数值变量 好处:
- 避免使用限制AttributeSets(见下文) 限制:
- 无法使用现有GameplayEffect工作流程(Cost GEs用于弹药等)
- 需要工作来覆盖关键功能UGameplayAbility以检查和应用弹药成本对枪支的浮标
使用独立的AttributeSet 好处:
- 可以使用现有GameplayAbility和GameplayEffect工作流程(Cost GEs用于弹药等)
- 设置非常小的项目集很简单 限制: -您必须AttributeSet为每种武器类型创建一个新类。ASCs只能在功能上拥有一个AttributeSet类的实例,因为更改为在数组中Attribute查找其AttributeSet类的第一个实例ASCs SpawnedAttributes。同一AttributeSet类的其他实例将被忽略。
- 由于之前AttributeSet每个AttributeSet类一个实例的原因,您只能在玩家的库存中拥有每种类型的武器之一。
- 删除 anAttributeSet是危险的。在 GASShooter 中,如果玩家从火箭中自杀,玩家会立即从他的物品栏中移除火箭发射器(包括 中AttributeSet的ASC)。当服务器复制火箭发射器的弹药Attribute改变时,AttributeSet客户端上不再存在,ASC游戏崩溃。
构造GameplayEffect并且修改参数
DamageEffectSpecHandle存储着FGameplayEffectSpec的智能指针。通过MakeOutgoingGameplayEffectSpec创建并且修改参数之后再通过ApplyGameplayEffectSpecToTarget应用到指定目标。
UPROPERTY(BlueprintReadOnly, EditAnywhere)
TSubclassOf<UGameplayEffect> DamageGameplayEffect;
FGameplayEffectSpecHandle DamageEffectSpecHandle = MakeOutgoingGameplayEffectSpec(DamageGameplayEffect, GetAbilityLevel());
// Pass the damage to the Damage Execution Calculation through a SetByCaller value on the GameplayEffectSpec
DamageEffectSpecHandle.Data.Get()->SetSetByCallerMagnitude(FGameplayTag::RequestGameplayTag(FName("Data.Damage")), Damage);
动态创建GE并且应用
// Create a dynamic instant Gameplay Effect to give the bounties
UGameplayEffect* GEBounty = NewObject<UGameplayEffect>(GetTransientPackage(), FName(TEXT("Bounty")));
GEBounty->DurationPolicy = EGameplayEffectDurationType::Instant;
int32 Idx = GEBounty->Modifiers.Num();
GEBounty->Modifiers.SetNum(Idx + 2);
FGameplayModifierInfo& InfoXP = GEBounty->Modifiers[Idx];
InfoXP.ModifierMagnitude = FScalableFloat(GetXPBounty());
InfoXP.ModifierOp = EGameplayModOp::Additive;
InfoXP.Attribute = UGDAttributeSetBase::GetXPAttribute();
FGameplayModifierInfo& InfoGold = GEBounty->Modifiers[Idx + 1];
InfoGold.ModifierMagnitude = FScalableFloat(GetGoldBounty());
InfoGold.ModifierOp = EGameplayModOp::Additive;
InfoGold.Attribute = UGDAttributeSetBase::GetGoldAttribute();
Source->ApplyGameplayEffectToSelf(GEBounty, 1.0f, Source->MakeEffectContext());
持续刷新GE,以延长持续时间
4.5.16 修改已激活GameplayEffect的持续时间
AGameplayAbilityTargetActor
4.11.1 Target Data 4.11.2 Target Actor 用于获取场景中的信息,或者在场景中生成一些东西。
Input绑定
如果你的ASC位于Character, 那么就在SetupPlayerInputComponent()中包含用于绑定到ASC的函数.
GASDocument上常用的Abilty和Effect
- 眩晕(Stun)
- 奔跑(Sprint)
- 瞄准(Aim Down Sight)
- 生命偷取(Lifesteal)
- 在客户端和服务端中生成随机数
- 暴击(Critical Hits)
- 非堆栈GameplayEffect, 但是只有其最高级(Greatest Magnitude)才能实际影响Target
- 游戏暂停时生成TargetData
- 按钮交互系统(Button Interaction System)