UE5多人MOBA+GAS 47、制作冰冻技能

发布于:2025-08-19 ⋅ 阅读:(15) ⋅ 点赞:(0)


添加寒冰技能

GA_Freeze
在这里插入图片描述

// 幻雨喜欢小猫咪

#pragma once

#include "CoreMinimal.h"
#include "GAS/Core/CGameplayAbility.h"
#include "GA_Freeze.generated.h"

/**
 * 冰冻技能:角色瞄准地面位置释放冰冻效果,对区域内敌人造成伤害
 */
UCLASS()
class UGA_Freeze : public UCGameplayAbility
{
	GENERATED_BODY()
public:	
	UGA_Freeze();
	// 激活技能
	virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;

private:
	// 目标选择半径(效果作用范围)
	UPROPERTY(EditDefaultsOnly, Category = "Targeting")
	float TargetingRadius = 1000.f;

	// 目标选择距离(最大施法距离)
	UPROPERTY(EditDefaultsOnly, Category = "Targeting")
	float TargetRange = 2000.f;

	// 地面目标选择器类
	UPROPERTY(EditDefaultsOnly, Category = "Targeting")
	TSubclassOf<class ATargetActor_GroundPick> TargetActorClass;

	// 瞄准阶段动画
	UPROPERTY(EditDefaultsOnly, Category = "Animation")
	TObjectPtr<UAnimMontage> FreezeTargetingMontage;

	// 施法阶段动画
	UPROPERTY(EditDefaultsOnly, Category = "Animation")
	TObjectPtr<UAnimMontage> FreezeCastMontage;

	// 伤害效果(冰冻伤害)
	UPROPERTY(EditDefaultsOnly, Category = "Effect")
	FGenericDamageEffectDef DamageEffect;

	// 目标位置视觉提示标签
	UPROPERTY(EditDefaultsOnly, Category = "GameplayCue")
	FGameplayTag FreezingTargetGameplayCueTag;

	// 冰冻效果视觉标签
	UPROPERTY(EditDefaultsOnly, Category = "GameplayCue")
	FGameplayTag FreezingGameplayCueTag;
	
	// 目标选择完成回调
	UFUNCTION()
	void TargetReceived(const FGameplayAbilityTargetDataHandle& TargetDataHandle);

	// 目标选择取消回调
	UFUNCTION()
	void TargetingCancelled(const FGameplayAbilityTargetDataHandle& TargetDataHandle);
};
#include "GA_Freeze.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"
#include "Abilities/Tasks/AbilityTask_WaitTargetData.h"
#include "GAS/TA/TargetActor_GroundPick.h"

UGA_Freeze::UGA_Freeze()
{
	// 添加瞄准状态标签
	ActivationOwnedTags.AddTag(TGameplayTags::Stats_Aim);
}

void UGA_Freeze::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
	const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	// 检查网络权限和预测键
	if (!HasAuthorityOrPredictionKey(CurrentActorInfo, &CurrentActivationInfo))
	{
		return;
	}
	
	// 任务1:播放瞄准动画(选择目标位置阶段)
	UAbilityTask_PlayMontageAndWait* PlayTargetingMontage = UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
		this, 
		NAME_None, 
		FreezeTargetingMontage // 使用瞄准动画
	);
	// 绑定动画结束事件到能力结束
	PlayTargetingMontage->OnBlendOut.AddDynamic(this, &UGA_Freeze::K2_EndAbility);
	PlayTargetingMontage->OnCancelled.AddDynamic(this, &UGA_Freeze::K2_EndAbility);
	PlayTargetingMontage->OnCompleted.AddDynamic(this, &UGA_Freeze::K2_EndAbility);
	PlayTargetingMontage->OnInterrupted.AddDynamic(this, &UGA_Freeze::K2_EndAbility);
	PlayTargetingMontage->ReadyForActivation(); // 启动任务

	// 任务2:创建目标选择器
	UAbilityTask_WaitTargetData* WaitTargetData = UAbilityTask_WaitTargetData::WaitTargetData(
		this, 
		NAME_None, 
		EGameplayTargetingConfirmation::UserConfirmed, // 需要玩家确认
		TargetActorClass
	);
	// 绑定目标选择完成和取消事件
	WaitTargetData->ValidData.AddDynamic(this, &UGA_Freeze::TargetReceived);
	WaitTargetData->Cancelled.AddDynamic(this, &UGA_Freeze::TargetingCancelled);
	WaitTargetData->ReadyForActivation();

	// 生成目标选择器实例
	AGameplayAbilityTargetActor* TargetActor;
	WaitTargetData->BeginSpawningActor(this, TargetActorClass, TargetActor);
	ATargetActor_GroundPick* GroundPickActor = Cast<ATargetActor_GroundPick>(TargetActor);
	if (GroundPickActor)
	{
		// 配置目标选择器参数
		GroundPickActor->SetShouldDrawDebug(ShouldDrawDebug()); // 是否显示调试信息
		GroundPickActor->SetTargetAreaRadius(TargetingRadius);  // 作用半径
		GroundPickActor->SetTargetTraceRange(TargetRange);      // 最大距离
	}
	
	// 完成生成
	WaitTargetData->FinishSpawningActor(this, TargetActor);
}

void UGA_Freeze::TargetReceived(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
	// 提交技能资源(如魔法值消耗)
	if (!K2_CommitAbility())
	{
		K2_EndAbility();
		return;
	}

	// 服务端:应用伤害效果
	if (K2_HasAuthority())
	{
		ApplyDamageToTargetDataHandle(TargetDataHandle, DamageEffect, GetAbilityLevel(CurrentSpecHandle, CurrentActorInfo));
	}

	// 创建冰冻特效参数
	FGameplayCueParameters FreezeCueParameters;
	// 从目标数据中获取命中位置作为特效的生成点
	FreezeCueParameters.Location = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(TargetDataHandle, 1).ImpactPoint;
	// 设置特效规模(使用目标半径)
	FreezeCueParameters.RawMagnitude = TargetingRadius;

	// 在目标位置播放冰冻特效(所有客户端可见)
	GetAbilitySystemComponentFromActorInfo()->ExecuteGameplayCue(FreezingGameplayCueTag, FreezeCueParameters);

	// 本地播放施法动画
	PlayMontageLocally(FreezeCastMontage);
	
	// 结束技能
	K2_EndAbility();
}

void UGA_Freeze::TargetingCancelled(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{
	// 取消目标选择时直接结束技能
	K2_EndAbility();
}

添加冷却标签

	CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Freeze_Cooldown)
	UE_DEFINE_GAMEPLAY_TAG_COMMENT(Ability_Freeze_Cooldown, "Ability.Freeze.Cooldown", "冻结技能冷却")

添加GC

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

添加GE

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
添加到GA中
在这里插入图片描述
在这里插入图片描述

添加到数据表

在这里插入图片描述
添加到角色中
在这里插入图片描述
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到