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); }