第一次提交
This commit is contained in:
@@ -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
|
||||
};
|
||||
Reference in New Issue
Block a user