文章目录
添加标签
cpp
CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Blink_Teleport)
CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Blink_Cooldown)
cpp
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Ability_Blink_Teleport, "Ability.Blink.Teleport", "闪烁技能")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Ability_Blink_Cooldown, "Ability.Blink.Cooldown", "闪烁技能冷却")
添加GA_Blink

cpp
#pragma once
#include "CoreMinimal.h"
#include "GAS/Core/CGameplayAbility.h"
#include "GA_Blink.generated.h"
/**
* 闪烁技能:角色选择目标位置进行传送,落地时对周围敌人造成伤害和击退
*/
UCLASS()
class CRUNCH_API UGA_Blink : public UCGameplayAbility
{
GENERATED_BODY()
public:
UGA_Blink();
// 激活技能
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
private:
// 瞄准阶段动画(选择目标位置)
UPROPERTY(EditDefaultsOnly, Category = "Anim")
TObjectPtr<UAnimMontage> TargetingMontage;
// 传送阶段动画
UPROPERTY(EditDefaultsOnly, Category = "Anim")
TObjectPtr<UAnimMontage> TeleportMontage;
// 地面目标选择器类
UPROPERTY(EditDefaultsOnly, Category = "Targeting")
TSubclassOf<class ATargetActor_GroundPick> GroundPickTargetActorClass;
// 落地伤害效果
UPROPERTY(EditDefaultsOnly, Category = "Effect")
FGenericDamageEffectDef DamageEffect;
// 落地击退速度
UPROPERTY(EditDefaultsOnly, Category = "Effect")
float BlinkLandTargetPushSpeed = 5000.f;
// 落地作用范围半径
UPROPERTY(EditDefaultsOnly, Category = "Targeting")
float TargetAreaRadius = 1000;
// 最大闪烁距离
UPROPERTY(EditDefaultsOnly, Category = "Targeting")
float BlinkCastRange = 3000.f;
// 目标选择完成回调
UFUNCTION()
void GroundPickTargetReceived(const FGameplayAbilityTargetDataHandle& TargetDataHandle);
// 目标选择取消回调
UFUNCTION()
void GroundPickCancelled(const FGameplayAbilityTargetDataHandle& TargetDataHandle);
// 传送事件回调(由动画事件触发)
UFUNCTION()
void Teleport(FGameplayEventData Payload);
// 缓存的目标位置数据
FGameplayAbilityTargetDataHandle BlinkTargetDataHandle;
};
cpp
#include "GA_Blink.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"
#include "Abilities/Tasks/AbilityTask_WaitGameplayEvent.h"
#include "Abilities/Tasks/AbilityTask_WaitTargetData.h"
#include "GAS/TA/TargetActor_GroundPick.h"
// #include "Abilities/Tasks/AbilityTask_ApplyRootMotionMoveToForce.h"
UGA_Blink::UGA_Blink()
{
ActivationOwnedTags.AddTag(TGameplayTags::Stats_Aim);
}
void UGA_Blink::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
// 检查网络权限和预测键
if (!HasAuthorityOrPredictionKey(ActorInfo, &ActivationInfo))
{
K2_EndAbility();
return;
}
// 任务1:播放瞄准动画
UAbilityTask_PlayMontageAndWait* PlayTargetingMontage = UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
this,
NAME_None,
TargetingMontage
);
PlayTargetingMontage->ReadyForActivation();
// 任务2:创建目标选择器
UAbilityTask_WaitTargetData* WaitBlinkLocationTargetData = UAbilityTask_WaitTargetData::WaitTargetData(
this,
NAME_None,
EGameplayTargetingConfirmation::UserConfirmed, // 需要玩家确认
GroundPickTargetActorClass
);
// 绑定目标选择完成和取消事件
WaitBlinkLocationTargetData->ValidData.AddDynamic(this, &UGA_Blink::GroundPickTargetReceived);
WaitBlinkLocationTargetData->Cancelled.AddDynamic(this, &UGA_Blink::GroundPickCancelled);
WaitBlinkLocationTargetData->ReadyForActivation();
// 生成目标选择器实例
AGameplayAbilityTargetActor* TargetActor;
WaitBlinkLocationTargetData->BeginSpawningActor(this, GroundPickTargetActorClass, TargetActor);
ATargetActor_GroundPick* GroundPickTargetActor = Cast<ATargetActor_GroundPick>(TargetActor);
if (GroundPickTargetActor)
{
// 配置目标选择器参数
GroundPickTargetActor->SetShouldDrawDebug(ShouldDrawDebug()); // 是否显示调试信息
GroundPickTargetActor->SetTargetAreaRadius(TargetAreaRadius); // 作用半径
GroundPickTargetActor->SetTargetTraceRange(BlinkCastRange); // 最大距离
}
// 完成生成
WaitBlinkLocationTargetData->FinishSpawningActor(this, TargetActor);
}
void UGA_Blink::GroundPickTargetReceived(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
// 提交技能资源(如魔法值消耗)
if (!K2_CommitAbility())
{
K2_EndAbility();
return;
}
// 缓存目标位置数据(传送完成后造成伤害用)
BlinkTargetDataHandle = TargetDataHandle;
// 确保在服务端或预测有效时执行
if (HasAuthorityOrPredictionKey(CurrentActorInfo, &CurrentActivationInfo))
{
// 任务3:播放传送动画
UAbilityTask_PlayMontageAndWait* PlayTeleportMontage = UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
this,
NAME_None,
TeleportMontage
);
// 绑定动画结束事件到能力结束
PlayTeleportMontage->OnBlendOut.AddDynamic(this, &UGA_Blink::K2_EndAbility);
PlayTeleportMontage->OnCancelled.AddDynamic(this, &UGA_Blink::K2_EndAbility);
PlayTeleportMontage->OnInterrupted.AddDynamic(this, &UGA_Blink::K2_EndAbility);
PlayTeleportMontage->OnCompleted.AddDynamic(this, &UGA_Blink::K2_EndAbility);
PlayTeleportMontage->ReadyForActivation();
// 任务4:在服务端监听传送事件(动画通知触发)
if (K2_HasAuthority())
{
UAbilityTask_WaitGameplayEvent* WaitTeleportTimePoint = UAbilityTask_WaitGameplayEvent::WaitGameplayEvent(
this,
TGameplayTags::Ability_Blink_Teleport
);
// 绑定传送事件回调
WaitTeleportTimePoint->EventReceived.AddDynamic(this, &UGA_Blink::Teleport);
WaitTeleportTimePoint->ReadyForActivation();
}
}
}
void UGA_Blink::GroundPickCancelled(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
K2_EndAbility();
}
void UGA_Blink::Teleport(FGameplayEventData Payload)
{
if (K2_HasAuthority())
{
// 从目标数据获取选择的传送位置
FHitResult PickedLocationHitResult = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(BlinkTargetDataHandle, 1);
FVector PickedTeleportLocation = PickedLocationHitResult.ImpactPoint;
// 将角色传送到目标位置
GetAvatarActorFromActorInfo()->SetActorLocation(PickedTeleportLocation);
// 对落点范围内的目标应用伤害效果
ApplyDamageToTargetDataHandle(
BlinkTargetDataHandle,
DamageEffect,
GetAbilityLevel(CurrentSpecHandle, CurrentActorInfo)
);
// 击退目标
PushTargetsFromOwnerLocation(BlinkTargetDataHandle, BlinkLandTargetPushSpeed);
}
}
位移的时候加一个动画通知


把技能添加到角色上
这样技能就齐全了