我们在技能伤害基类上面设置了对应的负面效果应用的配置项,用来实现技能的负面效果应用。
在之前实现火球术的负面效果时,我们我们在创建火球时,通过伤害基类上的创建技能配置用于后续应用。
在火球攻击到敌人时,通过函数库书写的通过配置项应用到目标,我们将所需的配置设置到GE实例上
然后在AS里应用伤害时,我们去判断当前伤害是否需要应用负面效果,来实现负面效果的应用,然后调用函数实现对GE的添加。
在实现负面效果时,GE会将对应的负面效果标签应用给目标ASC
我们可以以此为切入点,通过判断角色的ASC身上的是否包含某个负面标签,来切换动作。
实现负面效果属性
我们在角色基类上面增加一个属性,用于记录当前的角色是否处于眩晕状态
cpp
//当前角色是否处于眩晕状态
UPROPERTY(Replicated, BlueprintReadOnly)
bool bIsStunned = false;
接着,我们增加保护性的配置,首先是注册监听负面标签变动的函数,然后增加一个眩晕标签变动的回调。我们把设置角色移动速度的配置从敌人的类里搬到了基类,因为角色眩晕时是无法移动的,我们需要去修改角色的最大移动速度。
cpp
//注册用于监听负面标签变动的函数
void DeBuffRegisterChanged();
//眩晕标签变动后的回调
virtual void StunTagChanged(const FGameplayTag CallbackTag, int32 NewCount);
//当前角色的最大移动速度
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combat")
float BaseWalkSpeed = 600.f;
然后我们实现监听负面标签变动函数,通过ASC去监听它的标签变动,并绑定眩晕标签变动回调。
cpp
void ARPGCharacter::DeBuffRegisterChanged()
{
//监听眩晕标签变动
AbilitySystemComponent->RegisterGameplayTagEvent(FRPGGameplayTags::Get().DeBuff_Stun, EGameplayTagEventType::NewOrRemoved).AddUObject(this, &ARPGCharacter::StunTagChanged);
}
在眩晕标签变动回调里,我们根据角色身上的对应标签的数量,来设置变量的true或者false
cpp
void ARPGCharacter::StunTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
{
bIsStunned = NewCount > 0;
GetCharacterMovement()->MaxWalkSpeed = bIsStunned ? 0.f : BaseWalkSpeed;
}
接下来,就是需要在玩家角色类和敌人类里,初始化ASC完成后,调用监听函数
cpp
void ARPGHero::InitAbilityActorInfo()
{
ARPGPlayerState* PlayerStateBase = GetPlayerState<ARPGPlayerState>();
check(PlayerStateBase); //检测是否有效,无效会暂停游戏
//从playerState获取ASC和AS
AbilitySystemComponent = PlayerStateBase->GetAbilitySystemComponent();
AttributeSet = PlayerStateBase->GetAttributeSet();
//初始化ASC
AbilitySystemComponent->InitAbilityActorInfo(PlayerStateBase, this);
//触发Actor的技能信息设置回调
Cast<URPGAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
//注册监听负面标签变动
DeBuffRegisterChanged();
...
cpp
void ARPGEnemy::InitAbilityActorInfo()
{
AbilitySystemComponent->InitAbilityActorInfo(this, this);
Cast<URPGAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
//注册监听负面标签变动
DeBuffRegisterChanged();
...
到这里,眩晕的布尔值可以跟随标签进行变动了,我们可以在动画蓝图中,进行监听此值来修改动画。
在敌人的动画蓝图中,我们将角色实例保存
然后在动画更新时,来获取角色是否处于眩晕状态。
接着增加一个切换状态,切换条件就是我们新增的变量
状态里,我们增加一个Sequence Player,用于设置使用的播放动画。
接着,在敌人基础动画蓝图继承的子蓝图里,我们对资产进行覆盖
接着,我们修改玩家动画蓝图,也一样在动画更新时,去更新动画蓝图新增的变量,记录当前的眩晕状态
然后增加一个眩晕状态,直接将动画拖上来即可,然后增加一个状态别名,不需要每个状态去设置对于它的连线。
在状态别名里,我们可以设置哪些状态要在眩晕属性为true时,切换到此状态。
我们记得将Sequence Player的循环动画开启,角色在眩晕时,可以循环播放。
对于敌人角色,我们还需要修改它们的AI控制器,在角色眩晕状态时,将停止移动和攻击玩家,我们在黑板里增加一个布尔变量,用于记录当前角色是否处于眩晕状态
在进行攻击执行的上面,我们增加一个黑板装饰器,用于判断此变量
设置一下顺序
然后将键查询设置为未设置,如果眩晕属性为true,将执行观察器终止操作。
如果要测试在闪电链中当前函数是否也能够执行,我们可以在蓝图中,比如技能结束时,给命中目标应用一个创建的负面效果
我们可以在场景中只保留一个怪,然后运行时打开AI控制器,来查看属性变化。以及角色的动画状态。
实现角色眩晕状态终止操作
我们之前实现过,通过设置标签来阻止玩家的输入,教程里是通过在应用负面Buff时,给ASC增加对应的标签,我这里考虑不方便修改,所以,准备另辟蹊径,通过使用一个自动触发的技能来实现。
我们基于自定义的技能基类创建一个技能类,这样,在设置给角色是,它能够顺利的添加的角色身上。
我们这里新增加了一个技能标签,然后在Cancel Abilities with Tag里设置了所有主动技能的标签,在技能激活时,含有这些标签的技能都将被结束激活。
接着,我们将玩家操作对应的标签设置给ASC,玩家在眩晕状态进行这些操作时,将无法触发。
接着,就是重点,我们在触发器这里,增加一个索引,来监听负面标签是否存在,如果存在,此技能将自动激活,Trigger Source设置为Owned Tag Present,如果角色身上存在此标签,技能将处于激活状态,在失去此标签时,技能也将被终止。
增加Niagara系统用来表现眩晕状态
按照之前火焰的负面效果灼烧的做法,我们再声明一个系统,用于定义眩晕的表现效果
在初始化时,创建对应的组件
我们专门实现了一个负面组件,用于即插即用的组件,如果需要添加一个,直接在类上面创建即可,在类上面,我们会监听对应的标签变动,来实现对应的表现效果的显示和隐藏。
就这样,实现了对应的效果。
实现敌人持续受击效果
在敌人受到闪电链的攻击时,它将会受到一秒十次的攻击,所以受击也会一秒触发十次,效果不是很好,所以,我们将实现一个持续受击状态,在持续受击时,敌人将不在触发受击,而是持续播放循环受击效果。
我们在角色基础类里增加一个变量,设置为可复制,在多端都可以展示对应的效果。
cpp
//当前角色是否处于持续攻击状态
UPROPERTY(Replicated, BlueprintReadOnly)
bool IsBeingShocked = false;
在战斗接口里,增加两个函数,用于设置和获取参数
cpp
/**
* 获取角色是否处于闪电链攻击状态
* @return 布尔值,如果处于返回true
*/
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
bool IsBeingShocked() const;
/**
* 设置角色是否处于闪电链攻击状态
* @param bInShock
*/
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void SetIsBeingShocked(bool bInShock);
在角色基类里覆写一下
cpp
virtual void SetIsBeingShocked_Implementation(bool bInShock) override;
virtual bool IsBeingShocked_Implementation() const override;
实现函数
cpp
void ARPGCharacterBase::SetIsBeingShocked_Implementation(bool bInShock)
{
IsBeingShocked = bInShock;
}
bool ARPGCharacterBase::IsBeingShocked_Implementation() const
{
return IsBeingShocked;
}
在AS里设置敌人受击时增加额外的判断,判断当前目标是否处于持续受击状态
编译打开UE,我们在敌人基础动画蓝图里,在动画更新回调里增加对持续受击变量的获取
增加一个持续受击的状态切换
我们通过获取变量设置它的切换
然后在子动画蓝图里去设置实际使用的动画,记得播放器要设置循环播放
接下来,我们在命中目标后,如果目标继承了战斗接口,我们将其持续受击状态设置为true
额外目标也需要设置
记得在技能结束时,我们将其持续受击状态设置为false
将额外目标状态取消
实现眩晕效果
我们将在闪电链技能结束时,给主要目标施加一个眩晕效果。
所以,在技能结束,取消受击后,我们应用一个配置给目标
然后接着测试,查看技能结束是否显示眩晕
接着升级一级技能,查看是否能够扩散