UE5多人MOBA+GAS 19、创建升龙技能,以及带力的被动,为升龙技能添加冷却和消耗

文章目录


创建升龙拳的Tag以及受力被动的Tag

给这个技能添加标签

cpp 复制代码
CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Uppercut_Launch)
CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Passive_Launch_Activate)
cpp 复制代码
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Ability_Uppercut_Launch, "Ability.Uppercut.Launch", "升龙拳攻击")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Ability_Passive_Launch_Activate, "Ability.Passive.Launch.Activate", "击飞被动技能激活")

CGameplayAbility中添加绘制Debug的布尔变量(暂时对我没的没什么用)

cpp 复制代码
	UFUNCTION()
	FORCEINLINE bool ShouldDrawDebug() const { return bShouldDrawDebug; }
private:
	UPROPERTY(EditDefaultsOnly, Category = "Debug")
	bool bShouldDrawDebug = false;

创建升龙技能

添加上勾拳(升龙拳)技能,命名为UpperCut

cpp 复制代码
// 幻雨喜欢小猫咪

#pragma once

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

/**
 * 
 */
UCLASS()
class CRUNCH_API UUpperCut : public UCGameplayAbility
{
	GENERATED_BODY()
public:	
	// 激活技能时调用
	virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
private:
	// 上勾拳动画Montage
	UPROPERTY(EditDefaultsOnly, Category = "Animation")
	TObjectPtr<UAnimMontage> UpperCutMontage;
	
	// 启动击飞效果
	UFUNCTION()
	void StartLaunching(FGameplayEventData EventData);
};
cpp 复制代码
// 幻雨喜欢小猫咪


#include "UpperCut.h"

#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"

void UUpperCut::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
                                const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	if (!K2_CommitAbility())
	{
		K2_EndAbility();
		return;
	}
	// 服务器执行
	if (HasAuthorityOrPredictionKey(ActorInfo, &ActivationInfo))
	{
		UAbilityTask_PlayMontageAndWait* PlayUpperCutMontageTask = UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(this, NAME_None, UpperCutMontage);
		PlayUpperCutMontageTask->OnBlendOut.AddDynamic(this, &UUpperCut::K2_EndAbility);
		PlayUpperCutMontageTask->OnCancelled.AddDynamic(this, &UUpperCut::K2_EndAbility);
		PlayUpperCutMontageTask->OnCompleted.AddDynamic(this, &UUpperCut::K2_EndAbility);
		PlayUpperCutMontageTask->OnInterrupted.AddDynamic(this, &UUpperCut::K2_EndAbility);
		PlayUpperCutMontageTask->ReadyForActivation();
		
		UAbilityTask_WaitGameplayEvent* WaitLaunchEventTask = UAbilityTask_WaitGameplayEvent::WaitGameplayEvent(this, TGameplayTags::Ability_Uppercut_Launch);
		WaitLaunchEventTask->EventReceived.AddDynamic(this, &UUpperCut::StartLaunching);
		WaitLaunchEventTask->ReadyForActivation();
	}
}

void UUpperCut::StartLaunching(FGameplayEventData EventData)
{
	if (K2_HasAuthority())
	{
		// 获取命中目标的数量
		int32 HitResultCount = UAbilitySystemBlueprintLibrary::GetDataCountFromTargetData(EventData.TargetData);
	
		for (int32 i = 0; i < HitResultCount; ++i)
		{
			// 获取每个命中的HitResult
			FHitResult HitResult = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(EventData.TargetData, i);
			UE_LOG(LogTemp, Warning, TEXT("HitActorName:  %s"), *HitResult.GetActor()->GetName())
		}
	}
}

将升龙技能添加到角色中

蓝图继承并创建

直接复制基础攻击增加一个技能一

添加到映射中

将技能添加到角色中

创建一个击飞被动,供升龙激活技能

添加一个新的类GAP_Launched,作为击飞的被动技能

cpp 复制代码
// 幻雨喜欢小猫咪

#pragma once

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

/**
 * 被击飞能力类
 * 用于处理角色被击飞时的特殊能力逻辑
 */
UCLASS()
class UGAP_Launched : public UCGameplayAbility
{
	GENERATED_BODY()
public:
	// 构造函数
	UGAP_Launched();

	// 激活能力时调用
	virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
	
	// 获取击飞激活事件Tag
	static FGameplayTag GetLaunchedAbilityActivationTag();
};
cpp 复制代码
// 幻雨喜欢小猫咪


#include "GAP_Launched.h"

#include "GAS/Core/TGameplayTags.h"

UGAP_Launched::UGAP_Launched()
{
	// 设置网络执行策略为仅在服务器端执行
	NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerOnly;

	// 创建一个新的触发数据对象
	FAbilityTriggerData TriggerData;

	// 设置触发数据的触发源为游戏事件
	TriggerData.TriggerSource = EGameplayAbilityTriggerSource::GameplayEvent;

	// 设置触发数据的触发标签为击飞被动技能激活标签
	TriggerData.TriggerTag = TGameplayTags::Ability_Passive_Launch_Activate;

	// 将创建好的触发数据添加到能力触发器列表中
	AbilityTriggers.Add(TriggerData);
}

void UGAP_Launched::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
	const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	if (!K2_CommitAbility())
	{
		K2_EndAbility();
		return;
	}

	if (K2_HasAuthority())
	{
		// 推自己
		PushSelf(TriggerEventData->TargetData.Get(0)->GetHitResult()->ImpactNormal);
		K2_EndAbility();
	}
}

FGameplayTag UGAP_Launched::GetLaunchedAbilityActivationTag()
{
	return TGameplayTags::Ability_Passive_Launch_Activate;
}

CGameplayAbility中添加推动自身的力

cpp 复制代码
	// 推动自己(如击退/击飞)
	void PushSelf(const FVector& PushVel);
	void PushTarget(AActor* Target, const FVector& PushVel);
	
	// 获取拥有者角色指针
	ACharacter* GetOwningAvatarCharacter();
private:
	// 缓存的拥有者角色指针
	UPROPERTY()
	TObjectPtr<ACharacter> AvatarCharacter;
cpp 复制代码
void UCGameplayAbility::PushSelf(const FVector& PushVel)
{
	ACharacter* OwningAvatarCharacter = GetOwningAvatarCharacter();
	if (OwningAvatarCharacter)
	{
		OwningAvatarCharacter->LaunchCharacter(PushVel, true, true);
	}
}

void UCGameplayAbility::PushTarget(AActor* Target, const FVector& PushVel)
{
	// 目标为空则返回
	if (!Target) return;

	FGameplayEventData EventData;

	// 创建单目标命中数据对象
	FGameplayAbilityTargetData_SingleTargetHit* HitData = new FGameplayAbilityTargetData_SingleTargetHit;
	// 配置命中结果参数
	FHitResult HitResult;
	HitResult.ImpactNormal = PushVel; // 设置冲击方向为力的方向
	HitData->HitResult = HitResult;
	EventData.TargetData.Add(HitData);
	// 用标签激活技能
	UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(Target, UGAP_Launched::GetLaunchedAbilityActivationTag(), EventData);
}

ACharacter* UCGameplayAbility::GetOwningAvatarCharacter()
{
	if (!AvatarCharacter)
	{
		AvatarCharacter = Cast<ACharacter>(GetAvatarActorFromActorInfo());
	}
	return AvatarCharacter;
}

回到升龙技能中,实现力技能的添加,再添加一个伤害效果

cpp 复制代码
    // 上勾拳击飞阶段的伤害效果
    UPROPERTY(EditDefaultsOnly, Category = "Launch")
    TSubclassOf<UGameplayEffect> LaunchDamageEffect;
	
	// 上勾拳击飞速度
	UPROPERTY(EditDefaultsOnly, Category = "Launch", meta = (DisplayName = "击飞力的大小"))
	float UpperCutLaunchSpeed = 1000.f;
cpp 复制代码
void UUpperCut::StartLaunching(FGameplayEventData EventData)
{
	if (K2_HasAuthority())
	{
		// 获取命中目标的数量
		int32 HitResultCount = UAbilitySystemBlueprintLibrary::GetDataCountFromTargetData(EventData.TargetData);
		// 推动自己向上
		PushTarget(GetAvatarActorFromActorInfo(), FVector::UpVector * UpperCutLaunchSpeed);

		for (int32 i = 0; i < HitResultCount; ++i)
		{
			// 获取每个命中的HitResult
			FHitResult HitResult = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(EventData.TargetData, i);

			PushTarget(HitResult.GetActor(), FVector::UpVector * UpperCutLaunchSpeed);
			ApplyGameplayEffectToHitResultActor(HitResult, LaunchDamageEffect, GetAbilityLevel(CurrentSpecHandle, CurrentActorInfo));
  
		}
	}
}

为角色添加基础技能,因为是通过tag触发的,所以不用管输入

创建一个GE

然后一个升龙拳双方都起飞了

为技能添加冷却以及消耗

创建一个tag表示升龙的冷却,在冷却标签存在的时间内是无法再次使用此技能。

cpp 复制代码
CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Uppercut_Cooldown)
cpp 复制代码
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Ability_Uppercut_Cooldown, "Ability.Uppercut.Cooldown", "升龙拳技能冷却")

创建一个GE来设置拥有持续时间,在GA的冷却中添加该GE

将CD添加到GA中

创建一个GE作为开销

用技能就会耗蓝了

相关推荐
charley.layabox12 小时前
8月1日ChinaJoy酒会 | 游戏出海高端私享局 | 平台 × 发行 × 投资 × 研发精英畅饮畅聊
人工智能·游戏
遇见尚硅谷1 天前
C语言:游戏代码分享
c语言·开发语言·算法·游戏
上海云盾商务经理杨杨1 天前
标题:2025游戏反外挂终极指南:从DMA对抗到生态治理的全面防御体系
游戏·网络安全
科技每日热闻3 天前
双模秒切,体验跃迁!飞利浦EVNIA双模游戏显示器27M2N6801M王者降临!
游戏·计算机外设
KhalilRuan3 天前
Unity Demo——3D平台跳跃游戏笔记
笔记·游戏·unity·游戏引擎
~ 小团子3 天前
每日一SQL 【游戏玩法分析 IV】
数据库·sql·游戏
AA陈超4 天前
虚幻引擎UE5专用服务器游戏开发-20 添加基础能力类与连招能力
c++·游戏·ue5·游戏引擎·虚幻
晚云与城4 天前
三子棋游戏设计与实现(C 语言版)
游戏