public int GetContacts(out Wheel.ContactInfo leftContact, out Wheel.ContactInfo rightContact) { int contacts = 0; if (left.contactInfo.isOnFloor) { contacts++; } if (right.contactInfo.isOnFloor) { contacts++; } leftContact = left.contactInfo; rightContact = right.contactInfo; return(contacts); }
void AddWheelForces(Wheel.ContactInfo contact, int totalContacts, int totalWheels) { if (!(contact.isOnFloor && contact.wasAlreadyOnFloor)) { return; } float absForward = Mathf.Abs(contact.forwardRatio); float absSide = Mathf.Abs(contact.sidewaysRatio); float speedDecay = Time.fixedDeltaTime * 85f; float powerRatio = (float)(totalContacts * totalWheels); float inertiaPower = Mathf.Clamp01(SpeedRatio - Time.fixedDeltaTime * 10f) * CurStg.targetSpeed / powerRatio; //inertiaPower *= speedDecay; int gear = GetGear(); bool shouldGoBackwards = gear < 0 && (contact.forwardRatio <= 0 || accelOutput < 0); float powerInput, brakeInput, tCurve; if (!shouldGoBackwards) { powerInput = rawAccel; brakeInput = -rawFootbrake; tCurve = rawAccel; } else { powerInput = -rawFootbrake; brakeInput = rawAccel; tCurve = -rawFootbrake; } //target speed for the current gear float gearSpeed = EvalGearCurve(gear, tCurve) * CurStg.targetSpeed; //float gearSpeedInterp = Mathf.Lerp(EvalGearCurve(prevGear, tCurve) * CurStg.targetSpeed, gearSpeed , 0.5f); //motor power and/or inertia, relative to to input float accelPower = Mathf.Lerp(inertiaPower * speedDecay, gearSpeed / powerRatio, powerInput); //apply boost power accelPower *= Mathf.Lerp(1, CurStg.boostRatio, boost); //braking power, relative to input float brakePower = Mathf.Lerp(0, Mathf.Max(inertiaPower, accelPower * 0.9f), brakeInput); //effects of gravity, from direction of the wheels relative to gravity direction float gravForward = MathEx.DotToLinear(Vector3.Dot(LocalGravity.normalized, contact.forwardDirection)); float angVelDelta = contact.rootVelocity.magnitude * contact.forwardFriction * Mathf.Sign(contact.forwardRatio) - contact.angularVelocity; //calculations for forward velocity var motorVel = contact.forwardDirection * accelPower; var brakeVel = contact.rootVelocity.normalized * brakePower * Mathf.Lerp(contact.sideFriction, contact.forwardFriction, absForward) * CurStg.brakeEffectiveness; var addedGravVel = Vector3.ProjectOnPlane(contact.forwardDirection, contact.hit.normal) * LocalGravity.magnitude * gravForward * speedDecay; //support for slopes Vector3 nextForwardVel = motorVel - brakeVel + addedGravVel; //Vector3.ProjectOnPlane( motorVel - brakeVel +addedGravVel,contact.hit.normal); //calculations for drift cancel var frontCancel = -contact.forwardDirection * curVelocity.magnitude; var sideCancel = -contact.sideSlipDirection * curVelocity.magnitude; Vector3 driftCancel = Vector3.Lerp(-curVelocity * 0, -frontCancel * 0.707f + sideCancel, (absSide)); //calculations for sideways velocity Vector3 nextSidewaysVel = Vector3.Lerp( curVelocity * (Mathf.Clamp01(1f - Time.fixedDeltaTime * 10f * absSide.Cubed()) + 0.707f * drift), driftCancel * contact.sideFriction, absForward); //add mix of sideways velocity and drift cancelation to forward velocity, lerped by drift control modifier Vector3 nextDriftVel = Vector3.Lerp(nextForwardVel + nextSidewaysVel, nextForwardVel + driftCancel, CurStg.driftControl); //lerp between steering velocity and pure forward Vector3 nextMergedVel = Vector3.Slerp(nextDriftVel, nextForwardVel, absForward); //final velocity = merged velocities with traction control applied Vector3 nextFinalVel = contact.otherColliderVelocity + Vector3.Lerp(nextMergedVel, Quaternion.FromToRotation(transform.forward, contact.forwardDirection) * nextMergedVel, CurStg.tractionControl); // nextFinalVel -= contact.horizontalVelocity/powerRatio * MathEx.DotToLinear(absSide); /*if (contact.isOnFloor) * nextFinalVel -= nextFinalVel*Mathf.Max(0, 1 - (curVelocity.magnitude * Time.fixedDeltaTime)*powerRatio);*/ #if DEBUG if (nextMergedVel.VectorIsNaN()) { Debug.Assert(nextFinalVel.VectorIsNaN(), nextForwardVel + " " + nextSidewaysVel + " " + nextDriftVel + " " + absForward + " " + absSide); } #endif //*fake drag rBody.AddForceAtPosition( -(contact.pointVelocity / totalContacts) * 0.9f - Vector3.ProjectOnPlane(contact.horizontalPointVelocity / totalContacts, contact.forwardDirection) * totalWheels * 0.5f, //compensate drift contact.pushPoint, ForceMode.Acceleration); //motor rBody.AddForceAtPosition( nextFinalVel, contact.pushPoint, ForceMode.Acceleration); prevGear = gear; }