UE官网ARPG学习笔记2

Abilities are only supported in a C++ game because Attribute Sets must be a C++ subclass of UAttributeSet

URPGAttributeSet defines attributes for current/max health and manaattack and defense buffsmovement speed, and a temporary damage attribute used in the damage formula. 

Each of these attributes is defined as an FGameplayAttributeData structure, which stores a Base value that is only modified by permanent changes and a Current value which is modified by temporary buffs/debuffs. 

在很多游戏中,会有一个Core Attribute Set共享于player 和 enemy, 然后会由此继承一个另外的set用于player

Before attributes are modified, the PreAttributeChange function handles scaling the current health/mana with the max value.After attributes are modified, the PostGameplayEffectExecute function handles clamping and notifying other objects about the changes

The constructor for RPGCharacterBase is responsible for creating the URPGAbilitySystemComponent and URPGAttributeSet subobjects that enables gameplay effects to work.

Also, you may wish to spawn AttributeSets or AbilitySystemComponents when an Actor is first interacted with to avoid object overhead.

ARPGCharacterBase::AddStartupGameplayAbilities where it reads the list of PassiveGameplayEffects from the character Blueprint and applies them, at the current CharacterLevel. If CharacterLevel changes, it removes and re-adds them at the new level

 Here is what the GE_StatsBase gameplay effect used for NPCs looks like inside the Unreal Engine 4 (UE4) editor: 

 在modifier中会读表(maxhealth,characterlevel)获取当前等级maxhealth.

  to do damage, the RPGDamageExecution class is used。

The execution calculations consist of two parts, a set of capture declarations and an execution function。

struct RPGDamageStatics
{
	DECLARE_ATTRIBUTE_CAPTUREDEF(DefensePower);
	DECLARE_ATTRIBUTE_CAPTUREDEF(AttackPower);
	DECLARE_ATTRIBUTE_CAPTUREDEF(Damage);

	RPGDamageStatics()
	{
		// Capture the Target's DefensePower attribute. Do not snapshot it, because we want to use the health value at the moment we apply the execution.
		DEFINE_ATTRIBUTE_CAPTUREDEF(URPGAttributeSet, DefensePower, Target, false);

		// Capture the Source's AttackPower. We do want to snapshot this at the moment we create the GameplayEffectSpec that will execute the damage.
		// (imagine we fire a projectile: we create the GE Spec when the projectile is fired. When it hits the target, we want to use the AttackPower at the moment
		// the projectile was launched, not when it hits).
		DEFINE_ATTRIBUTE_CAPTUREDEF(URPGAttributeSet, AttackPower, Source, true);

		// Also capture the source's raw Damage, which is normally passed in directly via the execution
		DEFINE_ATTRIBUTE_CAPTUREDEF(URPGAttributeSet, Damage, Source, true);
	}
};

static const RPGDamageStatics& DamageStatics()
{
	static RPGDamageStatics DmgStatics;
	return DmgStatics;
}

URPGDamageExecution::URPGDamageExecution()
{
	RelevantAttributesToCapture.Add(DamageStatics().DefensePowerDef);
	RelevantAttributesToCapture.Add(DamageStatics().AttackPowerDef);
	RelevantAttributesToCapture.Add(DamageStatics().DamageDef);
}

通过宏去定义capture。在DEFINE_ATTRIBUTE_CAPTUREDEF(AttributeSet, Attribute,Target/Source, true/false(是否snapshot))

上面例如,防御力需要获取目标的并且不能snapshot,因为需要当GE实际发生的时候使用。

之后的攻击力和伤害值都是需要获取source的并且需要snapshot,因为就像射出子弹的一刻攻击力就已经确定,而不能等到子弹已经打到被击者身上。

 The capture declaration macros register information with the UE4 Editor, so Gameplay Effects can use the execution in your project.

For each captured attribute, the list of currently active temporary modifiers is captured along with their gameplay tags。

Then in URPGDamageExecution::Execute_Implementation it applies only those modifiers that match the Gameplay Tags that were passed in at effect execution time

After combining those modifiers to get a "calculated" number for DamageAttackPower, and DefensePower, it turns that into "final" damage using the formula SourceDamage * AttackPower / DefensePower.

	float DamageDone = Damage * AttackPower / DefensePower;
	if (DamageDone > 0.f)
	{
		OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(DamageStatics().DamageProperty, EGameplayModOp::Additive, DamageDone));
	}

 The final damage then turns into a Health modifier in URPGAttributeSet::PostGameplayEffectExecute

Melee Abilities In ARPG

GA_MeleeBase is the base for all the Melee abilities:

ActivateAbility is called when an ability starts, and CommitAbility is used to commit the Cost (Mana for ARPG generally) and Cooldown for an ability. EndAbility is called to tell the system that the ability is done executing. 

PlayMontageandWaitForEvent is an AbilityTask node, and corresponds to URPGAbilityTask_PlayMontageAndWaitForEvent

 AbilityTasks are special objects that define a set of static functions to create the task (PlayMontageAndWaitForEvent in this case), variables and functions used to execute the task

The way these tasks work is by first playing a Montage and then listening for a Gameplay Event to be emitted from the AbilitySystemComponent. If an emitted Gameplay Event matches the passed in EventTags it will activate the EventReceived execution pin with a tag and a payload that will then call the ApplyEffectContainer function. 

when the weapon actor overlaps a character.it constructs a GameplayEventData payload and passes in a Target Actor + Instigator.

It then sends a gameplay event using a tag set by an Anim Notify state placed in a Montage

when that event is triggered, the ability graph will then activate the EventReceived execution pin

 The ApplyEffectContainer node corresponds to URPGGameplayAbility::ApplyEffectContainer, which applies a set of gameplay effects.

 Each URPGGameplayAbility has a map of tags to FRPGGameplayEffectContainer structures

contain target information and a list of Gameplay Effects to apply.

 When the AM_Attack_Axe montage is executed, it indicates that when the Event.Montage.Shared.WeaponHit GameplayEvent is emitted it will execute the GE_PlayerAxeMelee effect, using the targeting class RPGTargetType_UseEventData. That target type is implemented in native C++ in the RPGTargetType.cpp file and extracts the target Actors and the hit results from the passed in EventData. The second element in that map executes the BurstPound** special attack, which is a skill that will be described later.

The ApplyEffectContainer does two things: First, it looks for a FRPGGameplayEffectContainer inside this map that matches the passed in tag. If it finds one, it creates a FRPGGameplayEffectContainerSpec containing TargetData and a list of EffectSpecs

Then, it applies that ContainerSpec, which will do the actual damage to the target. Target data is a FGameplayAbilityTargetDataHandle that points to an array of polymorphic target structures that contain hit results, Actors, or something else that is game specific.

 Each game using the Ability System will probably want to implement a system similar to ApplyEffectContainer, because it makes it easy to put Blueprint logic in a parent ability while placing the list of effects to execute in child Blueprints

However, each game will be slightly different, and if your game includes client prediction targeting it will be much more complicated than the version used in ARPG.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值