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
这个也没改的必要,因为进去这个状态需要让服务器知道的(做一些射线检测的时候)