Example #1
0
    void FixedUpdate()
    {
        if (StaticDataAccess.config == null)
        {
            Debug.LogWarning("StaticDataAccess.config not found");
            return;
        }
        if (StaticDataAccess.config.input == null)
        {
            Debug.LogWarning("StaticDataAccess.config.input not found");
            return;
        }

        if (StaticDataAccess.config.input.GetBtnReset())
        {
            transform.position = startPos;
            transform.rotation = startRot;
            rb.velocity        = Vector3.zero;
            rb.angularVelocity = Vector3.zero;

            if (lipo != null)
            {
                lipo.ChargeTo(lipo.maxVoltage);
            }
        }

        if (StaticDataAccess.config.input.GetBtnFlip())
        {
            RaycastHit rayHit;
            if (Physics.Raycast(transform.position, Vector3.down, out rayHit, LayerMask.GetMask("Terrain")))
            {
                transform.position = rayHit.point + Vector3.up * 3.0f;
            }
            else
            {
                transform.position += Vector3.up * 5.0f;
            }
            transform.rotation = Quaternion.identity;
            rb.velocity        = Vector3.zero;
            rb.angularVelocity = Vector3.zero;
        }

        float throttle = StaticDataAccess.config.input.GetAxisThrottle();
        float roll     = StaticDataAccess.config.input.GetAxisRoll();
        float pitch    = StaticDataAccess.config.input.GetAxisPitch();
        float yaw      = StaticDataAccess.config.input.GetAxisYaw();

        throttle = Mathf.Clamp01(throttle + idleThrottle);
        roll     = rateProfile.ApplyRoll(roll) * Mathf.Deg2Rad;
        pitch    = rateProfile.ApplyPitch(pitch) * Mathf.Deg2Rad;
        yaw      = rateProfile.ApplyYaw(yaw) * Mathf.Deg2Rad;

        pidRoll.ApplyProfile(pidProfile, PIDAxis.Roll);
        pidPitch.ApplyProfile(pidProfile, PIDAxis.Pitch);
        pidYaw.ApplyProfile(pidProfile, PIDAxis.Yaw);

        Vector3 localRot = transform.InverseTransformVector(rb.angularVelocity);
        float   rollOut  = pidRoll.Calculate(-localRot.z, roll);
        float   pitchOut = pidPitch.Calculate(localRot.x, pitch);
        float   yawOut   = pidYaw.Calculate(localRot.y, yaw);

        Vector3 force  = Vector3.zero;
        Vector3 torque = Vector3.zero;

        if (lipo == null)
        {
            force  = Vector3.up * throttle * thrust;
            torque = new Vector3(pitch, yaw, -roll);
        }
        else
        {
            float thrCurrent = 0.0f;
            float rotCurrent = 0.0f;
            if (powertrain == null)
            {
                thrCurrent = Mathf.Abs(throttle * 200);
                rotCurrent = new Vector3(pitch, yaw, -roll).magnitude * 20;
            }
            else
            {
                thrCurrent = powertrain.throttleCurrentCurve.Evaluate(throttle);
                // might need to tweak the scale
                rotCurrent = powertrain.throttleCurrentCurve.Evaluate(new Vector3(pitch, yaw, -roll).magnitude / 30.0f);
            }
            lipo.expectedCurrent = thrCurrent + rotCurrent;
            if (lipo.expectedCurrent > 0)
            {
                float thrFraction  = thrCurrent / lipo.expectedCurrent;
                float rotFraction  = rotCurrent / lipo.expectedCurrent;
                float power        = lipo.actualCurrent * lipo.totalVoltage;
                float groundEffect = 0.0f;
                if (groundEffectFactor > 0)
                {
                    RaycastHit rayHit;
                    if (Physics.Raycast(transform.position, Vector3.down, out rayHit, groundEffectHeight, LayerMask.GetMask("Terrain")))
                    {
                        groundEffect = (groundEffectHeight - rayHit.distance) * groundEffectFactor / groundEffectHeight;
                    }
                }

                if (powertrain == null)
                {
                    force  = 0.017f * Vector3.up * power * thrFraction * (1 + groundEffect);
                    torque = 0.01f * new Vector3(pitchOut, yawOut, -rollOut) * power * rotFraction;
                }
                else
                {
                    force  = 0.025f * Vector3.up * power * thrFraction * (1 + groundEffect);
                    torque = 0.07f * new Vector3(pitchOut, yawOut, -rollOut) * power * rotFraction;
                }
            }
        }

        if (propwashFactor > 0)
        {
            Vector2 forw2d   = new Vector2(transform.forward.x, transform.forward.z);
            Vector2 vel2d    = new Vector2(rb.velocity.x, rb.velocity.z);
            float   propwash = force.magnitude * propwashFactor * (1 - Vector2.Dot(forw2d.normalized, vel2d.normalized)) / (0.1f * vel2d.magnitude + 1.5f);
            if (vel2d.magnitude < 2.0f)
            {
                // fixes too much propwash while hovering
                propwash *= vel2d.magnitude + 0.05f;
            }
            quadMesh.localEulerAngles = new Vector3(
                UnityEngine.Random.Range(-1.0f, 1.0f),
                UnityEngine.Random.Range(-1.0f, 1.0f),
                UnityEngine.Random.Range(-1.0f, 1.0f)
                ) * propwash;
        }
        else
        {
            quadMesh.localEulerAngles = Vector3.zero;
        }

        float aoaSine = Vector3.Dot(transform.forward, rb.velocity.normalized);
        float drag    = Mathf.Lerp(areaFront, areaTop, Mathf.Abs(aoaSine)) * rb.velocity.sqrMagnitude * Cd;

        rb.drag = drag;
        if (torque.magnitude < 0.1f)
        {
            rb.angularDrag = rotDrag;
        }
        else
        {
            rb.angularDrag = rotDrag / 5.0f / Mathf.Max(1.0f, torque.magnitude);
        }

        rb.AddRelativeForce(force);
        rb.AddRelativeTorque(torque);
    }