第一次提交

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,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
};