// Request Games © All rights reserved // Source/TengriPlatformer/Movement/Core/TengriMovementConfig.cpp #include "TengriMovementConfig.h" FSurfaceThresholds UTengriMovementConfig::GetThresholds() const { FSurfaceThresholds Out; Out.WalkableZ = FMath::Cos(FMath::DegreesToRadians(WalkableAngleDeg)); Out.SteepSlopeZ = FMath::Cos(FMath::DegreesToRadians(SteepSlopeAngleDeg)); Out.WallZ = FMath::Cos(FMath::DegreesToRadians(WallAngleDeg)); return Out; } #if WITH_EDITOR void UTengriMovementConfig::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { Super::PostEditChangeProperty(PropertyChangedEvent); // ════════════════════════════════════════════════════════════════════════ // 1. CALCULATE JUMP PHYSICS // ════════════════════════════════════════════════════════════════════════ // Safety check to prevent division by zero const float ClampedTime = FMath::Max(TimeToJumpApex, 0.1f); // Calculate Gravity: g = (2 * h) / t^2 Gravity = (2.0f * MaxJumpHeight) / FMath::Square(ClampedTime); // Calculate Initial Velocity: v = g * t JumpVelocity = FMath::Abs(Gravity) * ClampedTime; // Calculate Min Jump Velocity: v_min = sqrt(2 * g * h_min) // This is the velocity we clamp to when button is released early MinJumpVelocity = FMath::Sqrt(2.0f * FMath::Abs(Gravity) * MinJumpHeight); // ════════════════════════════════════════════════════════════════════════ // 2. VALIDATION LOGGING // ════════════════════════════════════════════════════════════════════════ bool bHasErrors = false; // Validate angle hierarchy if (WalkableAngleDeg >= SteepSlopeAngleDeg) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: WalkableAngle (%.1f) should be less than SteepSlopeAngle (%.1f)"), WalkableAngleDeg, SteepSlopeAngleDeg); bHasErrors = true; } if (SteepSlopeAngleDeg >= WallAngleDeg) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: SteepSlopeAngle (%.1f) should be less than WallAngle (%.1f)"), SteepSlopeAngleDeg, WallAngleDeg); bHasErrors = true; } // Validate collision parameters if (MaxStepHeight <= 0.f) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: MaxStepHeight should be positive")); bHasErrors = true; } if (GroundSnapDistance <= 0.f) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: GroundSnapDistance should be positive")); bHasErrors = true; } // Validate jump parameters if (MinJumpHeight >= MaxJumpHeight) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: MinJumpHeight (%.1f) should be less than MaxJumpHeight (%.1f)"), MinJumpHeight, MaxJumpHeight); bHasErrors = true; } if (TimeToJumpApex <= 0.f) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: TimeToJumpApex should be positive")); bHasErrors = true; } // Validate air physics if (AirControl < 0.f || AirControl > 1.f) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: AirControl should be between 0 and 1 (current: %.2f)"), AirControl); bHasErrors = true; } if (FallingGravityScale < 1.f) { UE_LOG(LogTemp, Warning, TEXT("TengriMovementConfig: FallingGravityScale should be >= 1.0 (current: %.2f)"), FallingGravityScale); bHasErrors = true; } // Log calculated values for verification if (!bHasErrors) { UE_LOG(LogTemp, Log, TEXT("TengriMovementConfig: Calculated Physics - Gravity: %.1f, JumpVel: %.1f, MinJumpVel: %.1f"), Gravity, JumpVelocity, MinJumpVelocity); } } #endif