diff --git a/Assets/Scripts/AffectedProjectile.cs b/Assets/Scripts/AffectedProjectile.cs index 2ae7497..59784db 100644 --- a/Assets/Scripts/AffectedProjectile.cs +++ b/Assets/Scripts/AffectedProjectile.cs @@ -21,6 +21,7 @@ public class AffectedProjectile : ICloneable { public TerminalBallisticDetector terminalDetector = new TerminalBallisticDetector(); public float aliveVelocity = 0.01f; //When below this velocity, this projectile is dead + public float minimumAltitude = -10f; //Kill projectile below this altitude public bool Active { get; set; } = false; @@ -32,7 +33,7 @@ public class AffectedProjectile : ICloneable { public Affector_Gravity affGravity = new Affector_Gravity(); public Affector_Coriolis affCoriolis = new Affector_Coriolis(); public Affector_SpinTwist affSpinTwist = new Affector_SpinTwist(); - public Affector_WindDrag affWindDrag = new Affector_WindDrag(); + public Affector_WindDragCubed affWindDrag = new Affector_WindDragCubed(); public Default_TerminalCalculator termCalc = new Default_TerminalCalculator(); @@ -103,7 +104,8 @@ public virtual void Tick(float deltaTime) { } public virtual bool IsDead() { - return physicsTransform.Velocity.magnitude < aliveVelocity || physicsTransform.Position.y < -10; + return physicsTransform.Velocity.sqrMagnitude < aliveVelocity * aliveVelocity + || physicsTransform.Position.y < minimumAltitude; } public virtual object Clone() { @@ -115,7 +117,7 @@ public virtual object Clone() { newProj.affGravity = affGravity.Clone() as Affector_Gravity; newProj.affCoriolis = affCoriolis.Clone() as Affector_Coriolis; newProj.affSpinTwist = affSpinTwist.Clone() as Affector_SpinTwist; - newProj.affWindDrag = affWindDrag.Clone() as Affector_WindDrag; + newProj.affWindDrag = affWindDrag.Clone() as Affector_WindDragCubed; newProj.termCalc = termCalc.Clone() as Default_TerminalCalculator; diff --git a/Assets/Scripts/Environment/ProjectileEnvironmentData.cs b/Assets/Scripts/Environment/ProjectileEnvironmentData.cs index f97b5fd..3bde08f 100644 --- a/Assets/Scripts/Environment/ProjectileEnvironmentData.cs +++ b/Assets/Scripts/Environment/ProjectileEnvironmentData.cs @@ -71,4 +71,14 @@ public Vector3 GetGravity(float altitude) public float planetaryMass = 5.972E24f; const float gravitationalConstant = 6.67408E-11f; + + /// + /// Speed of sound in air at a given altitude, derived from temperature. + /// Uses the approximation c = sqrt(gamma * R * T) for dry air. + /// + public float GetSpeedOfSound(float altitude) { + float temperature = ProjectileAffectors.AltitudeAirTemperature(altitude); + // gamma (ratio of specific heats for air) = 1.4, R (specific gas constant for dry air) = 287.05 + return Mathf.Sqrt(1.4f * 287.05f * temperature); + } } diff --git a/Assets/Scripts/ProjLauncher/InternalBallistics.cs b/Assets/Scripts/ProjLauncher/InternalBallistics.cs index 8c935da..2cfd5f6 100644 --- a/Assets/Scripts/ProjLauncher/InternalBallistics.cs +++ b/Assets/Scripts/ProjLauncher/InternalBallistics.cs @@ -11,7 +11,8 @@ public float /// - /// Gets the recoil velocity. + /// Gets the recoil velocity using conservation of momentum. + /// Propellant gas velocity is approximated as half of muzzle velocity. /// /// The recoil velocity. /// Projectile mass in kg. @@ -24,12 +25,11 @@ public static float GetRecoilVelocity( float launcherMass, float muzzleVelocity ) { + // Conservation of momentum: launcher_mass * recoil_vel = proj_mass * muzzle_vel + prop_mass * gas_vel + // Gas velocity is typically approximated as ~0.5 * muzzle velocity return - Mathf.Sqrt( - ((projectileMass + propellantMass) - * muzzleVelocity * muzzleVelocity) - / launcherMass - ); + (projectileMass * muzzleVelocity + 0.5f * propellantMass * muzzleVelocity) + / launcherMass; } diff --git a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Coriolis.cs b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Coriolis.cs index 6569c39..9fa8e67 100644 --- a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Coriolis.cs +++ b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Coriolis.cs @@ -9,12 +9,11 @@ public class Affector_Coriolis : AffectorBase //public Affector_Coriolis() : base() //{ } - public override void Tick_PostPhysics(float deltaTime) + public override void Tick_PrePhysics(float deltaTime) { proj.physicsTransform.AddForce( GetCoriolisAcceleration(proj.physicsTransform.Velocity), - ForceMode.Acceleration, - deltaTime + ForceMode.Acceleration ); } diff --git a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Gravity.cs b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Gravity.cs index 156e5a8..1daad67 100644 --- a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Gravity.cs +++ b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_Gravity.cs @@ -16,12 +16,10 @@ public class Affector_Gravity : AffectorBase { public Vector3 Gravity => useAdvancedGravity ? GetGravity(proj.physicsTransform.Position.y) : gravity; - public override void Tick_PostPhysics(float deltaTime) { - //Debug.Log($"Gravity is running {gravity * deltaTime}"); + public override void Tick_PrePhysics(float deltaTime) { proj.physicsTransform.AddForce( Gravity, - ForceMode.Acceleration, - deltaTime + ForceMode.Acceleration ); } diff --git a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_SpinTwist.cs b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_SpinTwist.cs index 458fa40..d08190c 100644 --- a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_SpinTwist.cs +++ b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_SpinTwist.cs @@ -1,63 +1,59 @@ -using System.Collections; +using System.Collections; using System.Collections.Generic; using UnityEngine; -//[CreateAssetMenu(fileName = "SpinTwistAffector", menuName = "AProjectiles/Affectors/SpinTwistAffector")] [System.Serializable] public class Affector_SpinTwist : AffectorBase { - //public Affector_SpinTwist() : base() - //{ - //} + // Cumulative time of flight, needed for the empirical spin drift formula + float totalTOF = 0.0f; - public override void Tick_PostPhysics(float deltaTime) + public override void Tick_PrePhysics(float deltaTime) { - Vector3 pos = proj.physicsTransform.Position; - - pos += + float stability = GetMillerStability( + proj.projectileData.bulletMass, + proj.projectileData.bulletDiameter, + proj.projectileData.bulletLength, + proj.physicsTransform.SpinVelocity + ); + + float twist = proj.physicsTransform.SpinVelocity; + float lateralAccel = GetSpinDriftAcceleration(stability, totalTOF, deltaTime, twist); + + // Apply spin drift as a lateral acceleration perpendicular to velocity + Vector3 driftDirection = Quaternion.FromToRotation(Vector3.forward, proj.physicsTransform.Velocity.normalized) * - new Vector3( - GetSpinDrift( - GetMillerStability( - proj.projectileData.bulletMass, - proj.projectileData.bulletDiameter, - proj.projectileData.bulletLength, - proj.physicsTransform.SpinVelocity - ), - deltaTime, - proj.physicsTransform.SpinVelocity), - 0, 0); - //proj.physicsTransform.Position = pos; + Vector3.right; + + proj.physicsTransform.AddForce( + driftDirection * lateralAccel, + ForceMode.Acceleration + ); + + totalTOF += deltaTime; } #region Related Methods - public float GetSpinDrift(float millerStability, float deltaTime, float twist) + /// + /// Computes the lateral acceleration due to spin drift by differentiating + /// the empirical drift formula: D(t) = 0.03175 * (SG + 1.2) * t^1.83 + /// Derivative: a(t) = 0.03175 * (SG + 1.2) * 1.83 * t^0.83 + /// + public float GetSpinDriftAcceleration(float millerStability, float tof, float deltaTime, float twist) { - // For the source of this equation please visit - // https://loadoutroom.com/13415/reaper-tips-spin-drift-coriolis-effect/ - - //Please note that, when viewed from the rear: - //The bullet will drift to the right if spinning clockwise - //The bullet will drift to the left if spinning anticlockwise - //If this is being calculated on a bullet each physics tick, - //TOF can be replaced by the time delta between those ticks - - //The 'SG' value can be calculated using the 'MillerStability()' function - //(Multiplied by 0.0254 to convert from inches to metres) - - return 0.03175f * (millerStability + 1.2f) * Mathf.Pow(deltaTime, 1.83f) * Mathf.Sign(twist); + if (tof < 0.0001f) + return 0.0f; + // Analytical derivative of the empirical drift displacement formula + // (multiplied by 0.0254 to convert from inches to metres, then divided out by the + // empirical constant which was already adjusted — the 0.03175 already includes this) + return 0.03175f * (millerStability + 1.2f) * 1.83f * Mathf.Pow(tof, 0.83f) * Mathf.Sign(twist); } - float l, t; //Only initialize these once - - //Add in multiple stability methods - /// - /// Millers the stability. + /// Computes gyroscopic stability using the Miller twist rule. /// - /// The gyrospoic stability of the bullet. /// Bullet mass (kg). /// Bullet diameter (meters). /// Bullet length (meters). @@ -67,18 +63,14 @@ public float GetMillerStability(float bulletMass, float bulletDiameter, float bu // Equation data taken from: // https://en.wikipedia.org/wiki/Miller_twist_rule#References - - //Firstly, convert the inputted SI values into their imperial counterparts (For the equation) + // Convert SI values into their imperial counterparts (for the equation) bulletMass *= 15432.4f; //kg to grains bulletDiameter *= 39.3701f; //metres to inches bulletLength *= 39.3701f; //metres to inches twist *= 39.3701f; //metres to inches - //BulletLength(calibers) = BulletLength(inches) / BulletDiameter(inches) - //Twist(calibers ber turn) = Twist(inches per turn) / BulletDiameter(inches) - - l = bulletLength / bulletDiameter; - t = twist / bulletDiameter; + float l = bulletLength / bulletDiameter; + float t = twist / bulletDiameter; return (30 * bulletMass) / @@ -90,7 +82,6 @@ public float GetMillerStability(float bulletMass, float bulletDiameter, float bu ); } - #endregion } diff --git a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDrag - Copy.cs b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDrag - Copy.cs deleted file mode 100644 index 45ece5c..0000000 --- a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDrag - Copy.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -//[CreateAssetMenu(fileName = "DragWindAffector", menuName = "AProjectiles/Affectors/DragWindAffector")] -[System.Serializable] -public class Affector_WindDrag : AffectorBase -{ - //public Affector_WindDrag(AffectedProjectile projectile) : base(projectile) - //{ - //} - - #region Settings - - /// - /// Whether or not to use the variables from the global 'ProjectileEnvironment' component. - /// It's recommended that this be left on - /// - public bool useEnvironmentSettings = true; - - #region If Not Using Environment Settings - - /// - /// The air density in kg/m3. - /// - public float airDensity; - - /// - /// The velocity of the wind in m/s - /// - public Vector3 windVelocity = Vector3.zero; - - public Vector3 GetwindVelocity() - { - return useEnvironmentSettings ? - (Application.isPlaying ? ProjectileEnvironment.instance.environment.windVelocity : Vector3.positiveInfinity) - : - this.windVelocity; - - } - - #endregion - - #endregion - - //{TODO} Fix and update - //public override void Tick(float deltaTime) - //{ - // proj.AddForce( - // GetDragAndWindAcceleration( - // proj.velocity, proj.position.y, - // proj.projectileData.dragCoefficient, - // proj.projectileData.crossSectionalArea, - // proj.projectileData.bulletMass), - // ForceMode.Acceleration, - // deltaTime - // ); - //} - - #region Related Functions - - public Vector3 GetDragAndWindAcceleration( - Vector3 velocity, float altitude, - float dragCoefficient, float crossSectionalArea, float projectileMass) - { - Vector3 velDiff = windVelocity - velocity; - - return - GetAirDensity(altitude) * dragCoefficient * crossSectionalArea * - new Vector3( - Mathf.Sign(velDiff.x) * velDiff.x * velDiff.x, - Mathf.Sign(velDiff.y) * velDiff.y * velDiff.y, - Mathf.Sign(velDiff.z) * velDiff.z * velDiff.z - ) - / (2 * projectileMass); - - } - - float GetAirDensity(float altitude) - { - return - useEnvironmentSettings ? - ProjectileEnvironment.instance.environment.GetAirDensity(altitude) : - airDensity; - - } - - #endregion -} diff --git a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDrag - Copy.cs.meta b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDrag - Copy.cs.meta deleted file mode 100644 index 7ff063b..0000000 --- a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDrag - Copy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 177c2336db4326c4380372c5595fd4bc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDragCubed.cs b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDragCubed.cs index 34a2af2..b43bc30 100644 --- a/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDragCubed.cs +++ b/Assets/Scripts/ProjectileAffectors/Affectors/Affector_WindDragCubed.cs @@ -1,12 +1,9 @@ -using System.Collections; +using System.Collections; using System.Collections.Generic; using UnityEngine; -//[CreateAssetMenu(fileName = "DragWindCubedAffector", menuName = "AProjectiles/Affectors/CubedDragWindAffector")] [System.Serializable] public class Affector_WindDragCubed : AffectorBase { - //public Affector_WindDragCubed() : base() - //{ } #region Settings @@ -33,7 +30,6 @@ public Vector3 GetwindVelocity() { (Application.isPlaying ? ProjectileEnvironment.instance.environment.windVelocity : Vector3.positiveInfinity) : this.windVelocity; - } #endregion @@ -42,16 +38,29 @@ public Vector3 GetwindVelocity() { public DirectionalDragCube directionDragCube = new DirectionalDragCube(); - //{TODO}Update this to use the DirectionalDragCube - public override void Tick_PostPhysics(float deltaTime) { - proj.physicsTransform.AddForce( + public override void Tick_PrePhysics(float deltaTime) { + ProjectileData projData = proj.projectileData; + VirtualPhysicsTransform pt = proj.physicsTransform; + + float altitude = pt.Position.y; + + // Use Mach-dependent drag coefficient when advanced drag model is available + float cd; + if (projData.useAdvancedDragModel && projData.isGraphGenerated) { + float speedOfSound = GetSpeedOfSound(altitude); + float mach = pt.Velocity.magnitude / speedOfSound; + cd = projData.GetDragCoefficient(mach); + } else { + cd = projData.dragCoefficient; + } + + pt.AddForce( GetDragAndWindAcceleration( - proj.physicsTransform.Velocity, proj.physicsTransform.Position.y, - proj.projectileData.dragCoefficient, - proj.projectileData.CrossSectionalArea, - proj.projectileData.bulletMass), - ForceMode.Acceleration, - deltaTime + pt.Velocity, altitude, + cd, + projData.CrossSectionalArea, + projData.bulletMass), + ForceMode.Acceleration ); } @@ -60,17 +69,21 @@ public override void Tick_PostPhysics(float deltaTime) { public Vector3 GetDragAndWindAcceleration( Vector3 velocity, float altitude, float dragCoefficient, float crossSectionalArea, float projectileMass) { - Vector3 velDiff = windVelocity - velocity; + Vector3 velRelative = GetwindVelocity() - velocity; - return - GetAirDensity(altitude) * dragCoefficient * crossSectionalArea * - new Vector3( - Mathf.Sign(velDiff.x) * velDiff.x * velDiff.x, - Mathf.Sign(velDiff.y) * velDiff.y * velDiff.y, - Mathf.Sign(velDiff.z) * velDiff.z * velDiff.z - ) - / (2 * projectileMass); + // Drag acts along the relative velocity vector using its magnitude squared + float speed = velRelative.magnitude; + if (speed < 0.0001f) + return Vector3.zero; + // F_drag = 0.5 * rho * Cd * A * |v_rel|^2 * direction(v_rel) + // Since velRelative already has the direction and one factor of speed, + // we multiply by speed (not speed^2) and by velRelative (not normalized) + // a_drag = F_drag / m + return + (GetAirDensity(altitude) * dragCoefficient * crossSectionalArea * speed) + / (2 * projectileMass) + * velRelative; } float GetAirDensity(float altitude) { @@ -78,7 +91,13 @@ float GetAirDensity(float altitude) { useEnvironmentSettings ? ProjectileEnvironment.instance.environment.GetAirDensity(altitude) : airDensity; + } + float GetSpeedOfSound(float altitude) { + return + useEnvironmentSettings ? + ProjectileEnvironment.instance.environment.GetSpeedOfSound(altitude) : + 343.0f; } #endregion diff --git a/Assets/Scripts/ProjectileAffectors/TerminalBallistics/Default_TerminalCalculator.cs b/Assets/Scripts/ProjectileAffectors/TerminalBallistics/Default_TerminalCalculator.cs index e588a6c..936331a 100644 --- a/Assets/Scripts/ProjectileAffectors/TerminalBallistics/Default_TerminalCalculator.cs +++ b/Assets/Scripts/ProjectileAffectors/TerminalBallistics/Default_TerminalCalculator.cs @@ -44,11 +44,14 @@ protected virtual Tuple WillPen(TerminalBallisticsData penData) { //$$stoppingDist=\sqrt[3]{\frac{projMass * initVel^2}{targetDensity*projCrossArea * projDragCoefficient}} $$ //Heavily simplified model + float speedOfSound = ProjectileEnvironment.instance.environment.GetSpeedOfSound(physicsTransform.Position.y); + float mach = physicsTransform.Velocity.magnitude / speedOfSound; + float stoppingDist = Mathf.Pow( //3rd root - (projData.bulletMass * physicsTransform.VelocityMagnitude * physicsTransform.VelocityMagnitude) //{TODO} Make velocity relative to target + (projData.bulletMass * physicsTransform.VelocityMagnitude * physicsTransform.VelocityMagnitude) / - (targetDensity * projData.CrossSectionalArea * projData.GetDragCoefficient(physicsTransform.Velocity.magnitude / 343.0f)) //{TODO} Rewrite correctly! + (targetDensity * projData.CrossSectionalArea * projData.GetDragCoefficient(mach)) , (1.0f / 3.0f) ); @@ -60,8 +63,7 @@ protected virtual void Penetrate(TerminalBallisticsData penData, float stoppingD ProjectileData projData = penData.projectile.projectileData; VirtualPhysicsTransform physicsTransform = penData.projectile.physicsTransform; float targetDensity = 1000.0f; //{TODO} Hook this up - - //343.0f - Temporary hardcoded value - 1 mach in air ~= 343 m/s + float speedOfSound = ProjectileEnvironment.instance.environment.GetSpeedOfSound(physicsTransform.Position.y); ThicknessData objectThickness = ProjectileHelper.FindThickness( @@ -93,7 +95,7 @@ protected virtual void Penetrate(TerminalBallisticsData penData, float stoppingD ( ( projData.CrossSectionalArea * - projData.GetDragCoefficient(physicsTransform.Velocity.magnitude / 343.0f) * + projData.GetDragCoefficient(physicsTransform.Velocity.magnitude / speedOfSound) * targetDensity * objectThickness.thickness * objectThickness.thickness * objectThickness.thickness ) @@ -127,8 +129,7 @@ protected virtual void Richochet(TerminalBallisticsData penData) { penData.projectile.physicsTransform.Position = penData.hitInfo.point + (penData.hitInfo.normal * 0.01f); //{TODO} Tie this up together with how much energy we lose to the rigidbody //Restitution dependant richochet - PhysicMaterial physMat = - penData.hitInfo.collider.gameObject.GetComponent().material; + PhysicMaterial physMat = penData.hitInfo.collider.sharedMaterial; penData.projectile.physicsTransform.Velocity = (physMat == null) ? //If the hit object does not have a physics material, then just do a normal reflect diff --git a/Assets/Scripts/ProjectileStuff/ProjectileAffectors.cs b/Assets/Scripts/ProjectileStuff/ProjectileAffectors.cs index 36ffc7b..bfe4969 100644 --- a/Assets/Scripts/ProjectileStuff/ProjectileAffectors.cs +++ b/Assets/Scripts/ProjectileStuff/ProjectileAffectors.cs @@ -124,15 +124,15 @@ public static float WaterVapourPressure(float dewPointTemperature) // https://www.brisbanehotairballooning.com.au/calculate-air-density/ return (0.99999683f + dewPointTemperature * //0 - (-0.90826951f * (10 ^ -2) + dewPointTemperature * //1 - (0.78736169f * (10 ^ -4) + dewPointTemperature * //2 - (-0.61117958f * (10 ^ -6) + dewPointTemperature * //3 - (0.43884187f * (10 ^ -8) + dewPointTemperature * //4 - (-0.29883885f * (10 ^ -10) + dewPointTemperature * //5 - (0.21874425f * (10 ^ -12) + dewPointTemperature * //6 - (-0.17892321f * (10 ^ -14) + dewPointTemperature * //7 - (0.11112018f * (10 ^ -16) + dewPointTemperature * //8 - (-0.30994571f * (10 ^ -19))))))))))); + (-0.90826951e-2f + dewPointTemperature * //1 + (0.78736169e-4f + dewPointTemperature * //2 + (-0.61117958e-6f + dewPointTemperature * //3 + (0.43884187e-8f + dewPointTemperature * //4 + (-0.29883885e-10f + dewPointTemperature * //5 + (0.21874425e-12f + dewPointTemperature * //6 + (-0.17892321e-14f + dewPointTemperature * //7 + (0.11112018e-16f + dewPointTemperature * //8 + (-0.30994571e-19f)))))))))); } #endregion diff --git a/Assets/Scripts/VirtualPhysicsTransform.cs b/Assets/Scripts/VirtualPhysicsTransform.cs index 4f11a9e..c181152 100644 --- a/Assets/Scripts/VirtualPhysicsTransform.cs +++ b/Assets/Scripts/VirtualPhysicsTransform.cs @@ -37,6 +37,7 @@ public void Initialise(VirtualPhysicsTransform fromData) { prevRotVel = fromData.prevRotVel; mass = fromData.mass; + accel = fromData.accel; } #region Private Vars @@ -59,6 +60,10 @@ public void Initialise(VirtualPhysicsTransform fromData) { float mass = 1.0f; + // Accumulated acceleration for Velocity Verlet integration. + // Forces are accumulated here during PrePhysics, then applied in Tick. + Vector3 accel = Vector3.zero; + #endregion #region Properties @@ -137,7 +142,12 @@ public virtual void Tick(float deltaTime) { prevRot = rot; prevRotVel = rotVel; - pos += vel * deltaTime; + // Velocity Verlet integration: + // pos uses second-order correction for better trajectory accuracy + pos += vel * deltaTime + 0.5f * accel * deltaTime * deltaTime; + vel += accel * deltaTime; + accel = Vector3.zero; + rot *= Quaternion.LerpUnclamped(Quaternion.identity, RotationalVelocity, deltaTime); } @@ -156,17 +166,20 @@ public virtual void Tick(float deltaTime) { #region Physics + /// + /// Adds a force to this physics body. + /// For Acceleration/Force modes, the force is accumulated and applied during Tick() + /// using Velocity Verlet integration. The deltaTime parameter is ignored for these + /// modes as dt is applied during integration. + /// Impulse/VelocityChange are applied immediately. + /// public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force, float deltaTime = float.NaN) { - if (float.IsNaN(deltaTime)) - deltaTime = Time.deltaTime; - - //Debug.Log($"deltaTime: {deltaTime}, force: {force}"); switch (mode) { case ForceMode.Acceleration: - vel += force * deltaTime; + accel += force; return; case ForceMode.Force: - vel += (force / mass) * deltaTime; + accel += force / mass; return; case ForceMode.Impulse: vel += force / mass;