第一次提交

This commit is contained in:
不明不惑
2026-03-03 01:23:02 +08:00
commit 3e434877e8
1053 changed files with 102411 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "GCS_TraceDelegates.h"
#include "GCS_ActorOwnedObject.h"
#include "GCS_TraceSystemComponent.h"
#include "Abilities/GameplayAbilityTypes.h"
#include "DEPRECATED_GCS_CollisionTraceInstance.generated.h"
class UPrimitiveComponent;
class UGCS_AttackRequest_Base;
class UTargetingPreset;
class UGCS_AttackRequest_Melee;
class UGCS_TraceSystemComponent;
/**
* Object for managing collision trace instances.
* 管理碰撞检测实例的对象。
*/
UCLASS(Blueprintable, AutoExpandCategories = ("GCS"), Deprecated, meta=(DeprecationMessage="CollisionTraceInstance is nolonger required since GCS 1.5!"))
class GENERICCOMBATSYSTEM_API UDEPRECATED_GCS_CollisionTraceInstance : public UGCS_ActorOwnedObject
{
GENERATED_BODY()
friend UGCS_TraceSystemComponent;
public:
/**
* Gameplay tag for the trace instance.
* 碰撞检测实例的游戏标签。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GCS|Trace Settings", meta=(ExposeOnSpawn))
FGameplayTag TraceGameplayTag;
/**
* The primitive component used for tracing.
* 用于追踪的原始组件。
*/
UPROPERTY(BlueprintReadWrite, Category = "GCS|Trace Settings", meta=(ExposeOnSpawn))
TObjectPtr<UPrimitiveComponent> TracePrimitiveComponent;
/**
* Socket names on the primitive component for tracing.
* 原始组件上用于追踪的插槽名称。
*/
UPROPERTY(BlueprintReadWrite, Category = "GCS|Trace Settings", meta=(ExposeOnSpawn))
TArray<FName> TracePrimitiveComponentSocketNames;
/**
* Targeting preset for fetching target actors.
* 用于获取目标Actor的目标预设。
*/
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="GCS|Trace Settings", meta=(ExposeOnSpawn))
TObjectPtr<UTargetingPreset> TargetingPreset;
/**
* The actor that created this trace instance.
* 创建此碰撞检测实例的Actor。
*/
UPROPERTY(BlueprintReadOnly, Category = "GCS|Trace Settings")
TObjectPtr<AActor> TraceOwner = nullptr;
/**
* Associated information for this trace.
* 此碰撞检测的关联信息。
*/
UPROPERTY(VisibleAnywhere, Transient, Category = "GCS|Trace State")
FGameplayEventData TraceInformation;
/**
* Delegate for trace hit events.
* 碰撞检测命中事件的委托。
*/
UPROPERTY(BlueprintAssignable, BlueprintCallable)
FGCS_OnTraceHitSignature OnHit;
/**
* Delegate for trace state change events.
* 碰撞检测状态更改事件的委托。
*/
UPROPERTY(BlueprintAssignable, BlueprintCallable)
FGCS_OnTraceStateChangedSignature OnTraceStateChangedEvent;
/**
* The active duration of the trace instance.
* 碰撞检测实例的激活时间。
*/
UPROPERTY(BlueprintReadOnly, Category="GCS|Trace State")
float ActiveTime{0.0f};
/**
* Broadcasts a hit event.
* 广播命中事件。
* @param HitResult The hit result. 命中结果。
*/
UFUNCTION(BlueprintCallable, Category="GCS|Trace")
void BroadcastHit(const FHitResult& HitResult);
/**
* Broadcasts a state change event.
* 广播状态更改事件。
* @param bNewState The new state. 新状态。
*/
void BroadcastStateChanged(bool bNewState);
protected:
/**
* Initializes the trace instance.
* 初始化碰撞检测实例。
*/
UFUNCTION(BlueprintNativeEvent, Category = "GCS|Trace", meta=(BlueprintProtected))
void OnTraceBeginPlay();
virtual void OnTraceBeginPlay_Implementation();
/**
* Cleans up the trace instance.
* 清理碰撞检测实例。
* @note The instance is returned to the cache pool instead of being destroyed.
* @注意 实例被返回到缓存池而不是销毁。
*/
UFUNCTION(BlueprintNativeEvent, Category = "GCS|Trace", meta=(BlueprintProtected))
void OnTraceEndPlay();
virtual void OnTraceEndPlay_Implementation();
/**
* Handles trace ticking.
* 处理碰撞检测的tick。
* @param DeltaSeconds Time since last frame. 上一帧以来的时间。
*/
UFUNCTION(BlueprintNativeEvent, Category = "GCS|Trace", meta=(BlueprintProtected))
void OnTraceTick(float DeltaSeconds);
virtual void OnTraceTick_Implementation(float DeltaSeconds);
/**
* Handles trace state changes.
* 处理碰撞检测状态更改。
* @param bNewState The new state. 新状态。
*/
UFUNCTION(BlueprintNativeEvent, Category = "GCS|Trace", meta=(BlueprintProtected))
void OnTraceStateChanged(bool bNewState);
virtual void OnTraceStateChanged_Implementation(bool bNewState);
/**
* Actors hit during the active duration.
* 激活期间命中的Actor。
*/
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category="GCS|Trace State", AdvancedDisplay)
TArray<TObjectPtr<AActor>> HitActors;
public:
/**
* Sets the trace mesh information.
* 设置碰撞检测网格信息。
* @param NewPrimitiveComponent The new primitive component. 新原始组件。
* @param PrimitiveComponentSocketNames The socket names. 插槽名称。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|Trace")
void SetTraceMeshInfo(UPrimitiveComponent* NewPrimitiveComponent, TArray<FName> PrimitiveComponentSocketNames);
/**
* Checks if an actor can be hit.
* 检查是否可以命中Actor。
* @param ActorToCheck The actor to check. 要检查的Actor。
* @return True if the actor can be hit. 如果可以命中返回true。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, BlueprintNativeEvent, Category="GCS|Trace")
bool CanHitActor(const AActor* ActorToCheck) const;
bool CanHitActor_Implementation(const AActor* ActorToCheck) const;
/**
* Gets the source actor for the trace.
* 获取碰撞检测的源Actor。
* @return The source actor (e.g., weapon, bullet, or trace owner). 源Actor例如武器、子弹或TraceOwner
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|Trace")
AActor* GetTraceSourceActor() const;
/**
* Toggles the trace state.
* 切换碰撞检测状态。
* @param bNewState The new state (active traces tick and attempt to hit). 新状态激活的追踪会tick并尝试命中
*/
UFUNCTION(BlueprintCallable, Category = "GCS|Trace")
void ToggleTraceState(bool bNewState);
/**
* Indicates if the trace is active.
* 表示碰撞检测是否激活。
*/
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GCS|Trace")
bool bTraceActive{false};
protected:
/**
* Handles trace hit events.
* 处理碰撞检测命中事件。
* @param HitResult The hit result. 命中结果。
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "GCS|Trace", meta=(BlueprintProtected))
void OnTraceHit(const FHitResult& HitResult);
virtual void OnTraceHit_Implementation(const FHitResult& HitResult);
};

View File

@@ -0,0 +1,115 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GCS_TraceStructLibrary.h"
#include "Engine/CancellableAsyncAction.h"
#include "GCS_AsyncAction_CollisionTrace.generated.h"
class UGCS_TraceSystemComponent;
/**
* Async action for setting up and listening to collision trace hits.
* 设置并监听碰撞检测命中的异步动作。
*/
UCLASS()
class GENERICCOMBATSYSTEM_API UGCS_AsyncAction_CollisionTrace : public UCancellableAsyncAction
{
GENERATED_BODY()
public:
/**
* Creates and activates trace instances from definitions and listens for hits.
* 从定义创建并激活碰撞检测实例并监听命中。
* @param TraceSystem The collision trace system component. 碰撞检测系统组件。
* @param TraceDefinitions The traces definitions will be created and added to collision trace system. 要新建的碰撞实例的定义。
* @param PrimitiveComponent The primitive component for tracing. 用于追踪的原始组件。
* @param OptionalSourceObject The optional source object. 可选的源对象.
* @return The async action instance. 异步动作实例。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"))
static UGCS_AsyncAction_CollisionTrace* SetupAndListenForCollisionTraceHit(UGCS_TraceSystemComponent* TraceSystem, const TArray<FGCS_TraceDefinition>& TraceDefinitions,
UPrimitiveComponent* PrimitiveComponent, UObject* OptionalSourceObject = nullptr);
/**
* Activates the async action.
* 激活异步动作。
*/
virtual void Activate() override;
/**
* Cancels the async action.
* 取消异步动作。
*/
virtual void Cancel() override;
/**
* Delegate for collision trace hit events.
* 碰撞检测命中事件的委托。
*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FCollisionTraceSignature, const FGCS_TraceHandle, Handle, const FHitResult&, HitResult);
/**
* Called before trace instances are activated.
* 在激活碰撞检测实例前调用。
*/
/**
* Called before trace instances are activated.
* 在激活碰撞检测实例前调用。
*/
UPROPERTY(BlueprintAssignable)
FCollisionTraceSignature BeforeActive;
/**
* Fired when a trace instance hits something.
* 当碰撞检测实例命中某物时触发。
*/
UPROPERTY(BlueprintAssignable)
FCollisionTraceSignature OnHit;
protected:
/**
* Handles trace instance hit events.
* 处理碰撞检测实例命中事件。
* @param TraceHandle The trace instance. 碰撞检测实例。
* @param HitResult The hit result. 命中结果。
*/
UFUNCTION()
void TraceHitCallback(const FGCS_TraceHandle& TraceHandle, const FHitResult& HitResult);
/**
* The collision system component.
* 碰撞系统组件。
*/
UPROPERTY()
TWeakObjectPtr<UGCS_TraceSystemComponent> TraceSystem;
/**
* The primitive component for tracing.
* 用于追踪的原始组件。
*/
UPROPERTY()
TWeakObjectPtr<UPrimitiveComponent> SourceComponent;
/**
* The optional source object.
* 可选的源对象。
*/
UPROPERTY()
TWeakObjectPtr<UObject> SourceObject;
/**
* The trace definitions to create.
* 要创建的碰撞检测定义。
*/
UPROPERTY()
TArray<FGCS_TraceDefinition> TraceDefinitions;
/**
* The monitored trace instances.
* 监听的碰撞检测实例。
*/
UPROPERTY()
TArray<FGCS_TraceHandle> TraceHandles;
};

View File

@@ -0,0 +1,24 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GCS_TraceStructLibrary.h"
#include "UObject/Object.h"
#include "GCS_TraceDelegates.generated.h"
/**
* Delegate for trace instance hit events.
* 碰撞检测实例命中事件的委托。
*/
UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FGCS_OnTraceHitSignature, const FGCS_TraceHandle&, TraceHandle, const FHitResult&, HitResult);
UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FGCS_OnTraceStateChangedSignature, const FGCS_TraceHandle&, TraceHandle, bool, bNewState);
UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGCS_OnTraceStartedSignature, const FGCS_TraceHandle&, TraceHandle);
UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGCS_OnTraceStoppedSignature, const FGCS_TraceHandle&, TraceHandle);

View File

@@ -0,0 +1,40 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "GCS_TraceEnumLibrary.generated.h"
UENUM()
enum class EGCS_CollisionShapeType : uint8
{
Sphere,
Box,
Capsule
};
UENUM()
enum class EGCS_TraceSweepType : uint8
{
ByChannel,
ByObject,
ByProfile
};
UENUM()
enum class EGCS_TraceTickType : uint8
{
Default,
FixedFrameRate,
DistanceBased
};
UENUM()
enum class EGCS_TraceExecutionState : uint8
{
InProgress,
Stopped,
PendingStop
};

View File

@@ -0,0 +1,29 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GCS_TraceStructLibrary.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GCS_TraceFunctionLibrary.generated.h"
/**
* Blueprint function library for trace system utilities.
* 碰撞检测系统工具的蓝图函数库。
*/
UCLASS()
class GENERICCOMBATSYSTEM_API UGCS_TraceFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
/**
* Filter definitions with trace tag matches TagToMatch.
* 筛选与指定标签匹配的碰撞检测定义。
* @param Definitions The definitions to filter. 要筛选的定义。
* @param TagToMatch The tag to check. 要检查的标签。
* @return Matching definitions. 匹配的定义。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem|Utilities", Meta = (DefaultToSelf="Actor"))
static TArray<FGCS_TraceDefinition> FilterTraceDefinitionsByTag(const TArray<FGCS_TraceDefinition>& Definitions, const FGameplayTag& TagToMatch);
};

View File

@@ -0,0 +1,469 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "CollisionShape.h"
#include "CollisionQueryParams.h"
#include "Collision/GCS_TraceEnumLibrary.h"
#include "Engine/DataTable.h"
#include "StructUtils/InstancedStruct.h"
#include "UObject/Object.h"
#include "GCS_TraceStructLibrary.generated.h"
class UTargetingPreset;
class UGCS_TraceSystemComponent;
USTRUCT(BlueprintType)
struct FGCS_TraceSweepSetting
{
GENERATED_BODY()
/**
* The type of sweep to perform for collision detection.
* 执行碰撞检测的扫描类型。
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "GCS")
EGCS_TraceSweepType SweepType = EGCS_TraceSweepType::ByChannel;
/**
* The collision channel to use for channel-based sweeping.
* 用于基于通道扫描的碰撞通道。
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "GCS",
meta = (EditCondition = "SweepType == EGCS_TraceSweepType::ByChannel", EditConditionHides))
TEnumAsByte<ECollisionChannel> TraceChannel = ECC_Visibility;
/**
* The object types to use for object-based sweeping.
* 用于基于对象扫描的对象类型。
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "GCS",
meta = (EditCondition = "SweepType == EGCS_TraceSweepType::ByObject", EditConditionHides))
TArray<TEnumAsByte<ECollisionChannel>> ObjectTypes;
/**
* The collision profile name to use for profile-based sweeping.
* 用于基于配置扫描的碰撞配置名称。
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "GCS",
meta = (EditCondition = "SweepType == EGCS_TraceSweepType::ByProfile", EditConditionHides))
FName ProfileName = NAME_None;
/**
* Whether to trace against complex collision.
* 是否对复杂碰撞进行追踪。
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "GCS")
bool bTraceComplex = false;
};
/**
* Build collision shape by static parameters
* 通过静态参数构建碰撞形状。
* 在SourceComponent空间内的静态形状。
*/
USTRUCT(meta = (Hidden, DisplayName = "Collision Shape"))
struct GENERICCOMBATSYSTEM_API FGCS_CollisionShape
{
GENERATED_BODY()
virtual ~FGCS_CollisionShape() = default;
virtual bool InitializeShape(const UPrimitiveComponent* SourceComponent);
virtual FTransform GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const;
virtual FCollisionShape GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const;
};
/**
* Build collision shape by static parameters
* 通过静态参数构建碰撞形状。
* 在SourceComponent空间内的静态形状。
*/
USTRUCT(meta = (DisplayName = "Collision Shape (Static)"))
struct GENERICCOMBATSYSTEM_API FGCS_CollisionShape_Static : public FGCS_CollisionShape
{
GENERATED_BODY()
/**
* The type of collision shape to use.
* 要使用的碰撞形状类型。
*/
UPROPERTY(EditAnywhere, Category = "GCS")
EGCS_CollisionShapeType ShapeType = EGCS_CollisionShapeType::Sphere;
/**
* The orientation/rotation of the collision shape.
* 碰撞形状的方向/旋转。
*/
UPROPERTY(EditAnywhere, Category = "GCS",
meta = (EditCondition = "ShapeType != EGCS_CollisionShapeType::Sphere", EditConditionHides))
FRotator Orientation = FRotator::ZeroRotator;
/**
* The position offset of the collision shape.
* 碰撞形状的位置偏移。
*/
UPROPERTY(EditAnywhere, Category = "GCS")
FVector Offset = FVector::ZeroVector;
/**
* The radius of the sphere or capsule.
* 球体或胶囊体的半径。
*/
UPROPERTY(EditAnywhere, Category = "GCS",
meta = (EditCondition = "ShapeType != EGCS_CollisionShapeType::Box", EditConditionHides))
float Radius = 10.f;
/**
* The half height of the capsule.
* 胶囊体的半高。
*/
UPROPERTY(EditAnywhere, Category = "GCS",
meta = (EditCondition = "ShapeType == EGCS_CollisionShapeType::Capsule", EditConditionHides))
float HalfHeight = 10.f;
/**
* The half size of the box.
* 盒子的半尺寸。
*/
UPROPERTY(EditAnywhere, Category = "GCS",
meta = (EditCondition = "ShapeType == EGCS_CollisionShapeType::Box", EditConditionHides))
FVector HalfSize = FVector(10.f, 10.f, 10.f);
virtual bool InitializeShape(const UPrimitiveComponent* SourceComponent) override;
virtual FTransform GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const override;
virtual FCollisionShape GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const override;
};
/**
* Build dynamic collision shape by binding to shape component(Box/Sphere/Capsule).
* 通过绑定Shape组件(Box/Sphere/Capsule)构建动态碰撞形状。
* 在SourceComponent空间内的与SourceComponent进行匹配的形状。
*/
USTRUCT(meta = (DisplayName = "Collision Shape (Shape Based)"))
struct GENERICCOMBATSYSTEM_API FGCS_CollisionShape_ShapeBased : public FGCS_CollisionShape
{
GENERATED_BODY()
/**
* The type of collision shape to use.
* 要使用的碰撞形状类型。
*/
UPROPERTY(EditAnywhere, Category = "GCS")
EGCS_CollisionShapeType ShapeType = EGCS_CollisionShapeType::Sphere;
/**
* The orientation/rotation of the collision shape.
* 碰撞形状的方向/旋转。
*/
UPROPERTY(EditAnywhere, Category = "GCS",
meta = (EditCondition = "ShapeType != EGCS_CollisionShapeType::Sphere", EditConditionHides))
FRotator Orientation = FRotator::ZeroRotator;
UPROPERTY(EditAnywhere, Category = "GCS")
FVector Offset = FVector::ZeroVector;
UPROPERTY()
float Radius = 10.f;
UPROPERTY()
float HalfHeight = 10.f;
UPROPERTY()
FVector HalfSize = FVector(10.f, 10.f, 10.f);
virtual bool InitializeShape(const UPrimitiveComponent* SourceComponent) override;
virtual FTransform GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const override;
virtual FCollisionShape GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const override;
};
/**
* 在SourceComponent空间内跟随SourceComponent的某Socket/Bone运动的形状。
*/
USTRUCT(meta = (DisplayName = "Collision Shape (Attached)"))
struct GENERICCOMBATSYSTEM_API FGCS_CollisionShape_Attached : public FGCS_CollisionShape_Static
{
GENERATED_BODY()
/**
* Name of the socket or bone the shape will be attached to.
* 形状将附加到的插槽或骨骼的名称。
*/
UPROPERTY(EditAnywhere, Category="GCS")
FName SocketOrBoneName;
virtual bool InitializeShape(const UPrimitiveComponent* SourceComponent) override;
virtual FTransform GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const override;
};
/**
* Build dynamic capsule collision shape by mesh's sockets.
* 通过网格的指定Sockets构建动态碰撞形状。
*/
USTRUCT(meta = (DisplayName = "Collision Shape (Socket Based)"))
struct GENERICCOMBATSYSTEM_API FGCS_CollisionShape_SocketBased : public FGCS_CollisionShape
{
GENERATED_BODY()
/**
* The name of the starting socket on the mesh.
* 网格上起始插槽的名称。
*/
UPROPERTY(EditAnywhere, Category = "GCS")
FName MeshSocketStart = TEXT("TrailStart");
/**
* The name of the ending socket on the mesh.
* 网格上结束插槽的名称。
*/
UPROPERTY(EditAnywhere, Category = "GCS")
FName MeshSocketEnd = TEXT("TrailEnd");
/**
* Additional length offset for the socket-based shape.
* 基于插槽的形状的额外长度偏移。
*/
UPROPERTY(EditAnywhere, Category = "GCS")
float MeshSocketLengthOffset = 0;
/**
* The radius of the capsule.
* 胶囊体的半径。
*/
UPROPERTY(EditAnywhere, Category = "GCS")
float Radius = 10.f;
/**
* The orientation/rotation of the collision shape.
* 碰撞形状的方向/旋转。
*/
UPROPERTY()
FRotator Orientation = FRotator::ZeroRotator;
/**
* The position offset of the collision shape.
* 碰撞形状的位置偏移。
*/
UPROPERTY()
FVector Offset = FVector::ZeroVector;
/**
* The half height of the capsule.
* 胶囊体的半高。
*/
UPROPERTY()
float HalfHeight = 10.f;
virtual FTransform GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const override;
virtual bool InitializeShape(const UPrimitiveComponent* SourceComponent) override;
virtual FCollisionShape GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const override;
};
/**
* Structure for defining collision trace instances.
* 定义碰撞检测实例的结构。
*/
USTRUCT(BlueprintType)
struct GENERICCOMBATSYSTEM_API FGCS_TraceDefinition : public FTableRowBase
{
GENERATED_BODY()
FGCS_TraceDefinition();
/**
* Tag used as Trace identifier.
* 此Trace的Tag标识。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trace Settings", meta=(Categories="GGF.Combat.Trace"))
FGameplayTag TraceTag;
/**
* Defines the shape used for detecting hit results.
* 定义用于获取命中结果的形状。
*/
UPROPERTY(EditAnywhere, Category = "Trace Settings", meta=(ExcludeBaseStruct, BaseStruct = "/Script/GenericCombatSystem.GCS_CollisionShape"))
FInstancedStruct CollisionShape{FInstancedStruct::Make(FGCS_CollisionShape_Static())};
/**
* Settings for the sweep operation.
* 扫描操作的设置。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trace Settings")
FGCS_TraceSweepSetting SweepSetting;
/**
* The type of tick policy to use for this trace.
* 此Trace使用的tick策略类型。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trace Settings")
EGCS_TraceTickType TraceTickType{EGCS_TraceTickType::FixedFrameRate};
/**
* The fixed frame rate for ticking when using FixedFrameRate policy.
* 使用固定帧率策略时的固定帧率。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trace Settings",
meta = (EditCondition = "TraceTickType == EGCS_TraceTickType::FixedFrameRate", EditConditionHides))
int32 FixedTickFrameRate = 30;
/**
* The distance threshold for ticking when using DistanceBased policy.
* 使用基于距离策略时的距离阈值。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trace Settings",
meta = (EditCondition = "TraceTickType == EGCS_TraceTickType::DistanceBased", EditConditionHides))
int32 DistanceTickThreshold = 30;
/**
* The angle threshold for ticking when using DistanceBased policy (in degrees).
* 使用基于距离策略时的角度阈值(度)。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Trace Settings",
meta = (EditCondition = "TraceTickType == EGCS_TraceTickType::DistanceBased", EditConditionHides))
float AngleTickThreshold = 15.0f; // Degrees
bool IsValidDefinition() const;
FString ToString() const;
};
/**
* Simple struct used for trace query.
*/
USTRUCT(BlueprintType)
struct GENERICCOMBATSYSTEM_API FGCS_TraceHandle
{
GENERATED_BODY()
/**
* The gameplay tag identifying this trace.
* 标识此Trace的游戏标签。
*/
UPROPERTY(BlueprintReadOnly, Category = "GCS")
FGameplayTag TraceTag;
/**
* The unique GUID for this trace instance.
* 此Trace实例的唯一GUID。
*/
UPROPERTY(BlueprintReadOnly, Category = "GCS")
FGuid Guid;
/**
* The source object that created this trace.
* 创建此Trace的源对象。
*/
UPROPERTY(BlueprintReadOnly, Category = "GCS")
TWeakObjectPtr<UObject> SourceObject;
bool IsValidHandle() const;
// Equality operator
friend bool operator==(const FGCS_TraceHandle& A, const FGCS_TraceHandle& B)
{
return A.TraceTag == B.TraceTag &&
A.Guid == B.Guid &&
A.SourceObject == B.SourceObject;
}
// Inequality operator
friend bool operator!=(const FGCS_TraceHandle& A, const FGCS_TraceHandle& B)
{
return !(A == B);
}
// Hash function for TMap/TSet
friend uint32 GetTypeHash(const FGCS_TraceHandle& Handle)
{
uint32 Hash = GetTypeHash(Handle.TraceTag);
Hash = HashCombine(Hash, GetTypeHash(Handle.Guid));
Hash = HashCombine(Hash, GetTypeHash(Handle.SourceObject));
return Hash;
}
FString ToDebugString() const
{
FString TagName = TraceTag.ToString();
if (TraceTag.IsValid())
{
TArray<FString> TagNames;
TraceTag.ToString().ParseIntoArray(TagNames,TEXT("."));
if (TagNames.Num() > 0)
{
TagName = TagNames.Last();
}
}
return FString::Printf(TEXT("%s;%s"), *TagName, SourceObject.IsValid() ? *GetNameSafe(SourceObject.Get()) : TEXT("None"));
}
};
// 补帧数据.
struct FGCS_TraceSubTick
{
FTransform StartTransform;
FTransform EndTransform;
FTransform AverageTransform;
};
USTRUCT(BlueprintType)
struct FGCS_TraceState
{
GENERATED_BODY()
void ChangeExecutionState(bool bNewTraceState, bool bStopImmediate = true);
void UpdatePreviousTransform(const FTransform& Transform);
// Get the world space transform of this trace.
FTransform GetCurrentTransform() const;
// Begin Runtime references
UPROPERTY()
UWorld* World{nullptr};
UPROPERTY()
TObjectPtr<UPrimitiveComponent> SourceComponent{nullptr};
UPROPERTY()
TObjectPtr<UGCS_TraceSystemComponent> OwningSystem{nullptr};
// End Runtime references
// Begin Static Data
FGCS_TraceSweepSetting SweepSetting;
// End Static Data
// Begin runtime data
FGCS_TraceHandle Handle;
bool IsPendingRemoval = false;
// The modified dynamic shape.
FInstancedStruct Shape;
TArray<FTransform, TFixedAllocator<2>> TransformsOverTime;
EGCS_TraceExecutionState ExecutionState = EGCS_TraceExecutionState::Stopped;
FCollisionShape CollisionShapeOverTime;
TArray<FGCS_TraceSubTick> SubTicks;
EGCS_TraceTickType TickPolicy;
float TickInterval = 1 / 30;
float AngleThreshold = 15.0f; // Degrees
bool bShouldTickThisFrame = false;
float TimeSinceLastTick = 0;
// how long this state active?
//
float TimeSinceActive = 0;
int32 TotalTickNumDuringExecution = 0;
TArray<TObjectPtr<AActor>> HitActors;
FCollisionQueryParams CollisionParams;
FCollisionResponseParams ResponseParams;
FCollisionObjectQueryParams ObjectQueryParams;
// End runtime data
};

View File

@@ -0,0 +1,60 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GCS_TraceStructLibrary.h"
#include "DrawDebugHelpers.h"
#include "WorldCollision.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Subsystems/WorldSubsystem.h"
#include "GCS_TraceSubsystem.generated.h"
UCLASS()
class GENERICCOMBATSYSTEM_API UGCS_TraceSubsystem : public UTickableWorldSubsystem
{
GENERATED_BODY()
public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Tick(float DeltaTime) override;
virtual bool IsTickable() const override { return true; }
virtual TStatId GetStatId() const override { return TStatId(); }
FCriticalSection CriticalSection;
bool IsValidStateIdx(int32 StateIdx) const;
FGCS_TraceState& GetTraceStateAt(int Index);
int32 AddTraceState();
void RemoveTraceState(int Idx, FGuid Guid);
protected:
TArray<FGCS_TraceState> TraceStates;
bool RemovalLock = false;
uint32 TickIdx = 0;
void RemoveTraceStateAt(int Idx, FGuid Guid);
void PreTraceTick(const float DeltaTime);
void PostTraceTick();
// 计算所有用于碰撞检测的必须数据。
virtual void PrepareSubTicks(const float DeltaTime);
virtual void PerformSubTicks(const float DeltaTime);
static void PerformAsyncTrace(const FTransform& StartTransform, const FTransform& EndTransform, const FTransform& AverageTransform, UWorld* World,
const FGCS_TraceSweepSetting& TraceSettings,
const FCollisionShape& CollisionShape, const FCollisionQueryParams& CollisionParams,
const FCollisionResponseParams& CollisionResponseParams,
const FCollisionObjectQueryParams& ObjectQueryParams, const FTraceDelegate* InDelegate = nullptr);
virtual void HandleTraceResults(const FTraceHandle& InTraceHandle, FTraceDatum& InTraceDatum, int32 TraceStateIdx, uint32 InTickIdx, float InShapeTime);
#if ENABLE_DRAW_DEBUG
static void DrawDebug(const FVector& Start, const FVector& End, const FQuat& Rot, TArray<FHitResult> Hits, const FCollisionShape& CollisionShape, const UWorld* World,
const EDrawDebugTrace::Type DrawDebugType, float DrawDebugTime, const FLinearColor& DrawDebugColor, const FLinearColor& DrawDebugHitColor);
#endif
// 新增用于批量移除的Pending列表避免边遍历边修改
TArray<TPair<int32, FGuid>> PendingRemovals;
};

View File

@@ -0,0 +1,312 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "GameplayTagContainer.h"
#include "GCS_TraceDelegates.h"
#include "GCS_TraceStructLibrary.h"
#include "GCS_TraceSystemComponent.generated.h"
class UGCS_TraceSubsystem;
class UPrimitiveComponent;
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGCS_OnTraceSystemDestroyedSignature);
/**
* Component for managing collision trace instances.
* 管理碰撞检测实例的组件。
*/
UCLASS(ClassGroup=(GCS), meta=(BlueprintSpawnableComponent, PrioritizeCategories="GCS"), Blueprintable, HideCategories=(Sockets, Navigation, Tags, ComponentTick, ComponentReplication,
Cooking, AssetUserData, Replication))
class GENERICCOMBATSYSTEM_API UGCS_TraceSystemComponent : public UActorComponent
{
GENERATED_BODY()
friend UGCS_TraceSubsystem;
public:
/**
* Default constructor.
* 默认构造函数。
*/
UGCS_TraceSystemComponent(const FObjectInitializer& ObjectInitializer);
/**
* Gets the collision trace system component from an actor.
* 从Actor获取碰撞检测系统组件。
* @param Actor The actor to query. 要查询的Actor。
* @return The collision trace system component. 碰撞检测系统组件。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem", Meta = (DefaultToSelf="Actor"))
static UGCS_TraceSystemComponent* GetTraceSystemComponent(const AActor* Actor);
/**
* Finds the collision trace system component on an actor.
* 在Actor上查找碰撞检测系统组件。
* @param Actor The actor to query. 要查询的Actor。
* @param Component The found component (output). 找到的组件(输出)。
* @return True if found. 如果找到返回true。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem", Meta = (DefaultToSelf="Actor", ExpandBoolAsExecs="ReturnValue"))
static bool FindTraceSystemComponent(const AActor* Actor, UGCS_TraceSystemComponent*& Component);
/**
* Initializes the collision trace system.
* 初始化碰撞检测系统。
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "GCS|TraceSystem", meta=(DisplayName="Initialize Trace System"))
void OnInitialize();
virtual void OnInitialize_Implementation();
/**
* Deinitializes the collision trace system.
* 取消初始化碰撞检测系统。
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "GCS|TraceSystem", meta=(DisplayName="Deinitialize Trace System"))
void OnDeinitialize();
virtual void OnDeinitialize_Implementation();
/**
* Creates trace instances from definitions.
* 从定义创建碰撞检测实例。
* @param Definitions The trace definitions. 碰撞检测定义。
* @param SourceComponent The primitive component for tracing. 用于追踪的原始组件。
* @param SourceObject The source object. 源对象。
* @return The created trace instances. 创建的碰撞检测实例。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
TArray<FGCS_TraceHandle> AddTracesByDefinitions(const TArray<FGCS_TraceDefinition>& Definitions, UPrimitiveComponent* SourceComponent, UObject* SourceObject);
/**
* Creates trace instances from data table row handles.
* 从数据表行句柄创建碰撞检测实例。
* @param DefinitionHandles The data table row handles for trace definitions. 碰撞检测定义的数据表行句柄。
* @param SourceComponent The primitive component for tracing. 用于追踪的原始组件。
* @param SourceObject The source object. 源对象。
* @return The created trace instances. 创建的碰撞检测实例。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
TArray<FGCS_TraceHandle> AddTracesByDefinitionHandles(UPARAM(meta=(RowType="/Script/GenericCombatSystem.GCS_CollisionTraceDefinition"))
const TArray<FDataTableRowHandle>& DefinitionHandles, UPrimitiveComponent* SourceComponent, UObject* SourceObject);
/**
* Creates a single trace instance from a definition.
* 从定义创建单个碰撞检测实例。
* @param Definition The trace definition. 碰撞检测定义。
* @param SourceComponent The primitive component for tracing. 用于追踪的原始组件。
* @param SourceObject The source object. 源对象。
* @return The created trace instance. 创建的碰撞检测实例。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
FGCS_TraceHandle AddTraceByDefinition(const FGCS_TraceDefinition& Definition, UPrimitiveComponent* SourceComponent, UObject* SourceObject);
/**
* Starts traces by tags and source object.
* 通过标签和源对象启动碰撞检测。
* @param TraceTags The gameplay tags to match. 要匹配的游戏标签。
* @param SourceObject The source object. 源对象。
* @return The started trace instances. 启动的碰撞检测实例。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
TArray<FGCS_TraceHandle> StartTracesByTagsAndSource(const FGameplayTagContainer& TraceTags, const UObject* SourceObject);
/**
* Starts multiple traces by their handles.
* 通过句柄启动多个碰撞检测。
* @param TraceHandles The trace handles to start. 要启动的碰撞检测句柄。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
void StartTracesByHandles(const TArray<FGCS_TraceHandle>& TraceHandles);
/**
* Starts a single trace by its handle.
* 通过句柄启动单个碰撞检测。
* @param TraceHandle The trace handle to start. 要启动的碰撞检测句柄。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
void StartTraceByHandle(const FGCS_TraceHandle& TraceHandle);
/**
* Stops multiple traces by their handles.
* 通过句柄停止多个碰撞检测。
* @param TraceHandles The trace handles to stop. 要停止的碰撞检测句柄。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
void StopTracesByHandles(const TArray<FGCS_TraceHandle>& TraceHandles);
/**
* Stops a single trace by its handle.
* 通过句柄停止单个碰撞检测。
* @param TraceHandle The trace handle to stop. 要停止的碰撞检测句柄。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
void StopTraceByHandle(const FGCS_TraceHandle& TraceHandle);
/**
* Removes a trace by its handle.
* 通过句柄移除碰撞检测。
* @param TraceHandle The trace handle to remove. 要移除的碰撞检测句柄。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
void RemoveTraceByHandle(const FGCS_TraceHandle& TraceHandle);
/**
* Clears all active and cached trace instances.
* 清除所有激活和缓存的碰撞检测实例。
* @note OnTraceEndPlay event is not fired. OnTraceEndPlay事件不会触发。
*/
UFUNCTION(BlueprintCallable, Category = "GCS|TraceSystem")
void RemoveAllTraces();
/**
* Gets all trace handles with the specified tag.
* 获取具有指定标签的所有碰撞检测句柄。
* @param TraceToFind The gameplay tag to search for. 要搜索的游戏标签。
* @return Array of trace handles with the specified tag. 具有指定标签的碰撞检测句柄数组。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem")
TArray<FGCS_TraceHandle> GetTraceHandlesByTag(FGameplayTag TraceToFind) const;
/**
* Gets all trace handles created by the specified source object.
* 获取由指定源对象创建的所有碰撞检测句柄。
* @param SourceObject The source object to search for. 要搜索的源对象。
* @return Array of trace handles from the specified source. 来自指定源的碰撞检测句柄数组。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem")
TArray<FGCS_TraceHandle> GetTraceHandlesBySource(const UObject* SourceObject) const;
/**
* Gets all trace handles with the specified tags and source object.
* 获取具有指定标签和源对象的所有碰撞检测句柄。
* @param TraceTags The gameplay tags to match. 要匹配的游戏标签。
* @param SourceObject The source object to match. 要匹配的源对象。
* @return Array of trace handles matching the criteria. 匹配条件的碰撞检测句柄数组。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem")
TArray<FGCS_TraceHandle> GetTraceHandlesByTagsAndSource(const FGameplayTagContainer& TraceTags, const UObject* SourceObject) const;
/**
* Gets the source actor for the specified trace handle.
* 获取指定碰撞检测句柄的源Actor。
* @param TraceHandle The trace handle to query. 要查询的碰撞检测句柄。
* @return The source actor, or nullptr if not found. 源Actor如果未找到则返回nullptr。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem")
AActor* GetTraceSourceActor(const FGCS_TraceHandle& TraceHandle) const;
/**
* Gets the source component for the specified trace handle.
* 获取指定碰撞检测句柄的源组件。
* @param TraceHandle The trace handle to query. 要查询的碰撞检测句柄。
* @return The source component, or nullptr if not found. 源组件如果未找到则返回nullptr。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem")
UPrimitiveComponent* GetTraceSourceComponent(const FGCS_TraceHandle& TraceHandle) const;
/**
* Checks if the specified trace is currently active.
* 检查指定的碰撞检测当前是否激活。
* @param TraceHandle The trace handle to check. 要检查的碰撞检测句柄。
* @return True if the trace is active. 如果碰撞检测激活则返回true。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GCS|TraceSystem")
bool IsTraceActive(const FGCS_TraceHandle& TraceHandle) const;
virtual TArray<FGCS_TraceHandle> StartTraces(const FGameplayTagContainer& TraceTags, const UObject* SourceObject);
virtual TArray<FGCS_TraceHandle> AddTraces(const TArray<FGCS_TraceDefinition>& Definitions, UPrimitiveComponent* SourceComponent, UObject* SourceObject);
virtual TArray<FGCS_TraceHandle> AddTraces(const TArray<FDataTableRowHandle>& DefinitionHandles, UPrimitiveComponent* SourceComponent, UObject* SourceObject);
virtual FGCS_TraceHandle AddTrace(const FGCS_TraceDefinition& TraceDefinition, UPrimitiveComponent* SourceComponent, UObject* SourceObject);
virtual FGCS_TraceHandle AddTrace(const FDataTableRowHandle& TraceDefinitionHandle, UPrimitiveComponent* SourceComponent, UObject* SourceObject);
virtual void StartTraces(const TArray<FGCS_TraceHandle>& TraceHandles);
virtual void StartTrace(const FGCS_TraceHandle& TraceHandle);
virtual void StopTraces(const TArray<FGCS_TraceHandle>& TraceHandles);
virtual void StopTrace(const FGCS_TraceHandle& TraceHandle);
virtual void RemoveTraces(const TArray<FGCS_TraceHandle>& TraceHandles);
virtual void RemoveTrace(const FGCS_TraceHandle& TraceHandle);
/**
* Event fired when a trace hits something.
* 当碰撞检测命中某物时触发的事件。
*/
UPROPERTY(BlueprintAssignable, Category = "GCS|TraceSystem")
FGCS_OnTraceHitSignature OnTraceHitEvent;
/**
* Event fired when a trace state changes.
* 当碰撞检测状态改变时触发的事件。
*/
UPROPERTY(BlueprintAssignable, Category = "GCS|TraceSystem")
FGCS_OnTraceStateChangedSignature OnTraceStateChangedEvent;
/**
* Event fired when a trace starts.
* 当碰撞检测开始时触发的事件。
*/
UPROPERTY(BlueprintAssignable, Category = "GCS|TraceSystem")
FGCS_OnTraceStartedSignature OnTraceStartedEvent;
/**
* Event fired when a trace stops.
* 当碰撞检测停止时触发的事件。
*/
UPROPERTY(BlueprintAssignable, Category = "GCS|TraceSystem")
FGCS_OnTraceStoppedSignature OnTraceStoppedEvent;
/**
* Event fired when the trace system is destroyed.
* 当碰撞检测系统被销毁时触发的事件。
*/
FGCS_OnTraceSystemDestroyedSignature OnDestroyedEvent;
protected:
virtual void OnTraceHitDetected(const FGCS_TraceHandle& TraceHandle, const TArray<FHitResult>& HitResults, const float DeltaTime, const uint32 TickIdx);
virtual void OnTraceStateChanged(const FGCS_TraceHandle& TraceHandle, bool bNewState);
/**
* Called when the game starts.
* 游戏开始时调用。
*/
virtual void BeginPlay() override;
/**
* Called when the game ends.
* 游戏结束时调用。
* @param EndPlayReason The reason for ending. 结束原因。
*/
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void OnComponentDestroyed(bool bDestroyingHierarchy) override;
/**
* Whether to auto-initialize on BeginPlay and deinitialize on EndPlay.
* 是否在BeginPlay时自动初始化在EndPlay时自动取消初始化。
*/
UPROPERTY(EditAnywhere, Category = "GCS|TraceSystem")
bool bAutoInitialize{true};
/**
* Default trace definitions created on BeginPlay.
* 在BeginPlay时创建的默认碰撞检测定义。
* @note SourceComponent will be the actor's main mesh. 源组件会是Actor的主要mesh。
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "GCS|TraceSystem", meta=(TitleProperty="TraceTag"))
TArray<FGCS_TraceDefinition> TraceDefinitions;
FCriticalSection TraceDoneScopeLock;
TMap<FGCS_TraceHandle, int32> HandleToStateIdx;
TMultiMap<FGameplayTag, FGCS_TraceHandle> TagToHandles;
bool bInitialized = false;
};