241 lines
9.4 KiB
C++
241 lines
9.4 KiB
C++
// Request Games © All rights reserved
|
|
|
|
// Source/TengriPlatformer/Movement/Core/TengriMovementConfig.h
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Engine/DataAsset.h"
|
|
#include "TengriMovementConfig.generated.h"
|
|
|
|
// ============================================================================
|
|
// SURFACE THRESHOLDS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Pre-calculated cosine thresholds for surface classification.
|
|
* Generated from angle degrees in UTengriMovementConfig.
|
|
*/
|
|
USTRUCT(BlueprintType)
|
|
struct TENGRIPLATFORMER_API FSurfaceThresholds
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
/** Minimum Normal.Z for walkable floor (cos of max walkable angle) */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Thresholds")
|
|
float WalkableZ = 0.64f;
|
|
|
|
/** Minimum Normal.Z for steep slopes */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Thresholds")
|
|
float SteepSlopeZ = 0.08f;
|
|
|
|
/** Minimum Normal.Z for walls (below = ceiling/overhang) */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Thresholds")
|
|
float WallZ = -0.08f;
|
|
|
|
// === Classification Helpers ===
|
|
|
|
FORCEINLINE bool IsWalkable(const float NormalZ) const
|
|
{
|
|
return NormalZ >= WalkableZ;
|
|
}
|
|
|
|
FORCEINLINE bool IsSteepSlope(const float NormalZ) const
|
|
{
|
|
return NormalZ >= SteepSlopeZ && NormalZ < WalkableZ;
|
|
}
|
|
|
|
FORCEINLINE bool IsWall(const float NormalZ) const
|
|
{
|
|
return NormalZ >= WallZ && NormalZ < SteepSlopeZ;
|
|
}
|
|
|
|
FORCEINLINE bool IsOverhang(const float NormalZ) const
|
|
{
|
|
return NormalZ < WallZ;
|
|
}
|
|
};
|
|
|
|
// ============================================================================
|
|
// MOVEMENT CONFIG
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Data asset containing all movement system parameters.
|
|
* Create instances in Content Browser for different character types.
|
|
*/
|
|
UCLASS(BlueprintType)
|
|
class TENGRIPLATFORMER_API UTengriMovementConfig : public UDataAsset
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
// ========================================================================
|
|
// PHYSICS
|
|
// ========================================================================
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Physics")
|
|
float MaxSpeed = 800.0f;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Physics")
|
|
float Acceleration = 2048.0f;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Physics")
|
|
float Friction = 8.0f;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Physics")
|
|
float RotationSpeed = 360.0f;
|
|
|
|
/** Minimum speed (cm/s) required to rotate character toward movement */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Physics")
|
|
float MinSpeedForRotation = 10.0f;
|
|
|
|
// ========================================================================
|
|
// JUMP CONFIGURATION
|
|
// ========================================================================
|
|
|
|
/** Target height of the jump in cm (UE units) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Jump", meta = (ClampMin = "10.0"))
|
|
float MaxJumpHeight = 200.0f;
|
|
|
|
/** Minimum height for a short hop (when button is released early) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Jump", meta = (ClampMin = "1.0"))
|
|
float MinJumpHeight = 40.0f;
|
|
|
|
/** Time (seconds) to reach the peak of the jump. Defines "heaviness". */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Jump", meta = (ClampMin = "0.1", ClampMax = "2.0"))
|
|
float TimeToJumpApex = 0.5f;
|
|
|
|
// ========================================================================
|
|
// JUMP FEEL (TIMINGS)
|
|
// ========================================================================
|
|
|
|
/** Time (seconds) after falling off a ledge during which jump is still allowed */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Jump|Feel", meta = (ClampMin = "0.0"))
|
|
float CoyoteTime = 0.15f;
|
|
|
|
/** Time (seconds) to buffer a jump input before hitting the ground */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Jump|Feel", meta = (ClampMin = "0.0"))
|
|
float JumpBufferTime = 0.15f;
|
|
|
|
// ========================================================================
|
|
// AIR PHYSICS
|
|
// ========================================================================
|
|
|
|
/** Multiplier for acceleration when in air (0 = no control, 1 = full control) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Air Physics", meta = (ClampMin = "0.0", ClampMax = "1.0"))
|
|
float AirControl = 0.5f;
|
|
|
|
/** Friction applied while in air (usually 0 for platformers) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Air Physics")
|
|
float AirFriction = 0.0f;
|
|
|
|
// ========================================================================
|
|
// CALCULATED VALUES (READ ONLY)
|
|
// ========================================================================
|
|
|
|
/** Gravity magnitude calculated from Jump Height & Time */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Calculated")
|
|
float Gravity = 980.0f;
|
|
|
|
/** Initial Z velocity required to reach MaxJumpHeight */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Calculated")
|
|
float JumpVelocity = 0.0f;
|
|
|
|
/** Velocity cut-off for variable jump height */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Calculated")
|
|
float MinJumpVelocity = 0.0f;
|
|
|
|
// ========================================================================
|
|
// AIR PHYSICS
|
|
// ========================================================================
|
|
|
|
/** Multiplier for gravity when falling. Makes jump feel "heavy" and snappy. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Air Physics", meta = (ClampMin = "1.0"))
|
|
float FallingGravityScale = 1.5f;
|
|
|
|
/** Maximum falling speed (cm/s). Prevents infinite acceleration. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Air Physics", meta = (ClampMin = "0.0"))
|
|
float TerminalVelocity = 2000.0f;
|
|
|
|
/** Z velocity threshold to consider a landing "heavy" (e.g. for landing animation/shake) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Air Physics")
|
|
float HeavyLandVelocityThreshold = -1000.0f;
|
|
|
|
// ========================================================================
|
|
// SURFACE ANGLES
|
|
// ========================================================================
|
|
|
|
/** Maximum angle (degrees) that counts as walkable floor */
|
|
UPROPERTY(EditAnywhere, Category = "Surface Angles", meta = (ClampMin = "0", ClampMax = "89"))
|
|
float WalkableAngleDeg = 50.0f;
|
|
|
|
/** Maximum angle for steep slopes (limited movement) */
|
|
UPROPERTY(EditAnywhere, Category = "Surface Angles", meta = (ClampMin = "0", ClampMax = "89"))
|
|
float SteepSlopeAngleDeg = 85.0f;
|
|
|
|
/** Maximum angle for walls (above = ceiling) */
|
|
UPROPERTY(EditAnywhere, Category = "Surface Angles", meta = (ClampMin = "90", ClampMax = "180"))
|
|
float WallAngleDeg = 95.0f;
|
|
|
|
// ========================================================================
|
|
// COLLISION
|
|
// ========================================================================
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collision")
|
|
int32 MaxSlideIterations = 3;
|
|
|
|
/** Maximum height of step that can be walked over */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collision")
|
|
float MaxStepHeight = 45.0f;
|
|
|
|
// ========================================================================
|
|
// GROUND SNAPPING
|
|
// ========================================================================
|
|
|
|
/** Distance to search for ground when snapping */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ground Snapping")
|
|
float GroundSnapDistance = 20.0f;
|
|
|
|
/** Micro-offset above ground to prevent floor penetration */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ground Snapping")
|
|
float GroundSnapOffset = 0.15f;
|
|
|
|
// ========================================================================
|
|
// SLOPE PHYSICS
|
|
// ========================================================================
|
|
|
|
/** Velocity damping on steep slopes (0 = full stop, 1 = full slide) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Physics", meta = (ClampMin = "0", ClampMax = "1"))
|
|
float SteepSlopeSlideFactor = 0.0f;
|
|
|
|
// ========================================================================
|
|
// FIXED TIMESTEP
|
|
// ========================================================================
|
|
|
|
/** Physics update rate in Hz (default: 120) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fixed Timestep",
|
|
meta = (ClampMin = "30", ClampMax = "240"))
|
|
float PhysicsTickRate = 120.0f;
|
|
|
|
/** Maximum accumulated time before clamping (prevents spiral of death) */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fixed Timestep",
|
|
meta = (ClampMin = "0.05", ClampMax = "0.5"))
|
|
float MaxAccumulatedTime = 0.1f;
|
|
|
|
/** Enable interpolation between physics states */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fixed Timestep")
|
|
bool bEnableInterpolation = true;
|
|
|
|
// ========================================================================
|
|
// API
|
|
// ========================================================================
|
|
|
|
/** Converts degree angles to cosine thresholds for runtime use */
|
|
FSurfaceThresholds GetThresholds() const;
|
|
|
|
#if WITH_EDITOR
|
|
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
|
#endif
|
|
};
|