예제 #1
0
            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);
            }
예제 #2
0
        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;
        }