UE5多人MOBA+GAS 31、修改一下GC的触发

发布于:2025-07-29 ⋅ 阅读:(17) ⋅ 点赞:(0)

文章目录


AN_SendTargetGroup添加一个GC以及激活的GC的函数

	// 触发的GameplayCue标签(如命中特效、音效等)
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability")
	FGameplayTagContainer TriggerGameplayCueTags;

	// 触发本地GameplayCue(如播放命中特效、音效等)
	void SendLocalGameplayCue(const FHitResult& HitResult) const;
#pragma once

#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "GenericTeamAgentInterface.h"
#include "Animation/AnimNotifies/AnimNotify.h"
#include "AN_SendTargetGroup.generated.h"

/**
 * 
 */
UCLASS()
class UAN_SendTargetGroup : public UAnimNotify
{
	GENERATED_BODY()
public:
	virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override;

private:
	// 触发的GameplayCue标签(如命中特效、音效等)
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability")
	FGameplayTagContainer TriggerGameplayCueTags;
	
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability", meta = (DisplayName = "目标阵营"))
	TEnumAsByte<ETeamAttitude::Type> TargetTeam = ETeamAttitude::Hostile;

	// 球形检测半径
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability", meta = (DisplayName = "球体半径"))
	float SphereSweepRadius = 60.f;

	// 是否绘制调试轨迹
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability", meta = (DisplayName = "绘制调试轨迹"))
	bool bDrawDebug = false;
	
	// 是否忽略自己
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability", meta = (DisplayName = "忽略自身"))
	bool bIgnoreOwner = true;
	
	// 发送的Tag
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability")
	FGameplayTag EventTag;
	
	// 骨骼名称
	UPROPERTY(EditAnywhere, Category = "Gameplay Ability")
	TArray<FName> TargetSocketNames;

	// 触发本地GameplayCue(如播放命中特效、音效等)
	void SendLocalGameplayCue(const FHitResult& HitResult) const;
};
#include "Animations/AN_SendTargetGroup.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemGlobals.h"
#include "GameplayCueManager.h"
#include "GenericTeamAgentInterface.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Player/CPlayerController.h"


void UAN_SendTargetGroup::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
                                 const FAnimNotifyEventReference& EventReference)
{
	Super::Notify(MeshComp, Animation, EventReference);
	// 检查MeshComp有效性
	if (!MeshComp)
		return;

	// 至少需要两个Socket才能进行连线检测
	if (TargetSocketNames.Num() <= 1)
		return;

	// 检查拥有者和能力系统组件有效性
	if (!MeshComp->GetOwner() || !UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(MeshComp->GetOwner()))
	{
		return;
	}
	
	FGameplayEventData Data;         // 用于存储命中目标数据
	
	TArray<AActor*> HitActors;         // 记录已命中的Actor,避免重复
	AActor* OwnerActor = MeshComp->GetOwner();
	const IGenericTeamAgentInterface* OwnerTeamInterface = Cast<IGenericTeamAgentInterface>(OwnerActor);
	
	for (int32 i = 1; i < TargetSocketNames.Num(); i++)
	{
		// 获取攻击的前一个位置和当前位置
		FVector StartLoc = MeshComp->GetSocketLocation(TargetSocketNames[i - 1]);
		FVector EndLoc = MeshComp->GetSocketLocation(TargetSocketNames[i]);
	
		// 设置检测对象类型为Pawn
		TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
		ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_Pawn)); // 只检测Pawn类型
		TArray<FHitResult> HitResults; // 用于存储命中结果
	
		TArray<AActor*> IgnoredActors; // 忽略的Actor
		if (bIgnoreOwner)
		{
			IgnoredActors.Add(OwnerActor);// 忽略自身
		}
	
		EDrawDebugTrace::Type DrawDebugTrace = bDrawDebug ? EDrawDebugTrace::ForDuration : EDrawDebugTrace::None;
	
		// 球形多重检测,查找路径上的所有目标
		UKismetSystemLibrary::SphereTraceMultiForObjects(
			MeshComp, StartLoc, EndLoc, SphereSweepRadius, 
			ObjectTypes, false, IgnoredActors, DrawDebugTrace, HitResults, false);
	
		// 遍历所有命中结果
		for (const FHitResult& HitResult : HitResults)
		{
			// 忽略已命中的Actor
			AActor* HitActor = HitResult.GetActor();
			// 已经命中过的Actor不再处理
			if (!HitActor || HitActors.Contains(HitActor))
			{
				continue;
			}
			// UE_LOG(LogTemp, Warning, TEXT("ActorName:  %s, %d"), *HitResult.GetActor()->GetName(), i)
			HitActors.AddUnique(HitActor);
			// 检查目标阵营关系(如只攻击敌人)
			if (OwnerTeamInterface)
			{
				if (OwnerTeamInterface->GetTeamAttitudeTowards(*HitResult.GetActor()) != TargetTeam)
				{
					continue;
				}
			}
			//FString TargetSide = UEnum::GetValueAsString(OwnerTeamInterface->GetGenericTeamId().GetId());
			// UE_LOG(LogTemp, Warning, TEXT("打中了!!!:%u"), OwnerTeamInterface->GetGenericTeamId().GetId());
			
			// 创建命中数据并添加到事件数据中
			FGameplayAbilityTargetData_SingleTargetHit* TargetHit = new FGameplayAbilityTargetData_SingleTargetHit(HitResult);
			Data.TargetData.Add(TargetHit);
	
			SendLocalGameplayCue(HitResult);
		}
	}

	// 向拥有者发送GameplayEvent,带上所有命中目标数据
	UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(MeshComp->GetOwner(), EventTag, Data);
}

void UAN_SendTargetGroup::SendLocalGameplayCue(const FHitResult& HitResult) const
{
	FGameplayCueParameters CueParameters;
	CueParameters.Location = HitResult.ImpactPoint;
	CueParameters.Normal = HitResult.ImpactNormal;

	// 触发所有触发的GameplayCue
	for (const FGameplayTag& Tag : TriggerGameplayCueTags)
	{
		UAbilitySystemGlobals::Get().GetGameplayCueManager()->HandleGameplayCue(
			HitResult.GetActor(), Tag, EGameplayCueEvent::Executed, CueParameters);
	}
}

到蒙太奇的动画通知中添加GC
在这里插入图片描述
GE中的GC就可以删除了
在这里插入图片描述
修改一番GC
在这里插入图片描述
这个也没改的必要,因为进去这个状态需要让服务器知道的(做一些射线检测的时候)
在这里插入图片描述


网站公告

今日签到

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