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