using System;
using UnityEngine;
namespace Framework.Actors {
/// Contains helper methods for dealing with actor physics problems
public static class PhysicsHelper {
/// Calculates the jump-off velocity to reach a certain height
/// Gravity force affecting the actor (assumed to be constant)
///
/// Height for which the required jump-off velocity will be calculated
///
/// The average delta time of your physics updates
/// The jump-off velocity required to reach the specified height
///
///
/// All integration methods for Newtonian physics (Euler, Midpoint, Verlet, Runge Kutta)
/// introduce errors depending on delta time (physics framerate). For example,
/// a jump force for 2.0 units will lead to the following heights:
///
///
///
/// framerateactual jump height
///
/// - 1200 fps1.99 units
/// - 120 fps1.97 units
/// - 60 fps1.94 units
///
///
/// This method uses a compensation curve to achieve the desired apex height
/// by slightly increasing the jump-off impulse according to height and framerate.
/// For some amusing anecdotes, read about Quake3 jump height issues (a multiplayer
/// shooter where players with high FPS could jump higher and further...)
///
///
public static float GetJumpOffImpulse(
float gravity, float apexHeight, float physicsDeltaTime
) {
// Target jump height and actually required apex height to achieve it
// at different framerates:
//
// target | 120 fps | 60 fps | 30 fps
// ------------------------------------
// 1.0 | 1.042 | 1.090 | ?
// 2.0 | 2.059 | 2.124 | 2.292
// 3.0 | 3.074 | 3.152 | 3.350
// 4.0 | 4.084 | 4.171 | 4.358
// 5.0 | 5.094 | 5.192 | 5.431
// 6.0 | 6.102 | 6.216 | 6.447
// 7.0 | 7.111 | 7.227 | 7.469
// 8.0 | 8.118 | 8.239 | 8.494
// 9.0 | 9.126 | 9.253 | 9.521
// 10.0 | 10.132 | 10.266 | 10.548
// 20.0 | 20.186 | 20.376 | 20.768
// 30.0 | 30.228 | 30.457 | 30.930
// 40.0 | 40.261 | 40.537 | 41.064
// 50.0 | 50.293 | 50.598 | 51.211
// 60.0 | 60.322 | 60.651 | 61.317
// 70.0 | 70.347 | 70.696 | 71.435
// 80.0 | 80.371 | 80.743 | 81.502
// 90.0 | 90.395 | 90.794 | 91.581
// 100.0 | 100.414 | 100.833 | 101.712
//
if(physicsDeltaTime > 0.0f) {
float adjust30 = 0.1880608f * Mathf.Pow(apexHeight, 0.4751134f);
float adjust60 = 0.08728325f * Mathf.Pow(apexHeight, 0.4898834f);
float adjust120 = 0.04207374f * Mathf.Pow(apexHeight, 0.4967337f);
float t = Mathf.Log((1.0f / physicsDeltaTime) / 30.0f, 2.0f);
if(t < 2.0f) {
apexHeight += Mathf.LerpUnclamped(adjust30, adjust60, t - 1.0f);
} else {
apexHeight += Mathf.LerpUnclamped(adjust60, adjust120, t - 2.0f);
}
}
return Mathf.Sqrt(2.0f * gravity * apexHeight);
}
/// Calculates the required jump-off velocity to reach a certain height
/// Strength of gravity
///
/// Height for which the required jump-off velocity will be calculated
///
/// The jump-off velocity required to reach the specified height
///
/// Using this impulse on your character will not achieve the intended
/// jump height unless you're runnning physics at crazy low update intervals.
/// See for a compensating version.
///
public static float GetTheoreticalJumpOffImpulse(float gravity, float apexHeight) {
return Mathf.Sqrt(2.0f * gravity * apexHeight);
}
}
} // namespace Framework.Actors