void FixedUpdateBuoyancy(ICollProvider collProvider) { float archimedesForceMagnitude = WATER_DENSITY * Mathf.Abs(Physics.gravity.y); for (int i = 0; i < _forcePoints.Length; i++) { FloaterForcePoints point = _forcePoints[i]; var transformedPoint = transform.TransformPoint(point._offsetPosition + new Vector3(0, _centerOfMass.y, 0)); Vector3 undispPos; if (!collProvider.ComputeUndisplacedPosition(ref transformedPoint, _samplingData, out undispPos)) { // If we couldn't get wave shape, assume flat water at sea level undispPos = transformedPoint; undispPos.y = OceanRenderer.Instance.SeaLevel; } Vector3 displaced; collProvider.SampleDisplacement(ref undispPos, _samplingData, out displaced); var dispPos = undispPos + displaced; var heightDiff = dispPos.y - transformedPoint.y; if (heightDiff > 0) { RB.AddForceAtPosition(archimedesForceMagnitude * heightDiff * Vector3.up * point._weight * _forceMultiplier / _totalWeight, transformedPoint); } } }
void FixedUpdateEngine() { var forcePosition = RB.position; var forward = _engineBias; //if (_playerControlled) forward += Input.GetAxis("Vertical"); if (_playerControlled) { forward += joystick.Vertical; } RB.AddForceAtPosition(transform.forward * _enginePower * forward, forcePosition, ForceMode.Acceleration); var sideways = _turnBias; //if (_playerControlled) sideways += (Input.GetKey(KeyCode.A) ? -1f : 0f) + (Input.GetKey(KeyCode.D) ? 1f : 0f); //if (_playerControlled) sideways += (Input.GetKey(KeyCode.A) ? -1f : 0f) + (Input.GetKey(KeyCode.D) ? 1f : 0f); if (_playerControlled) { sideways = sideways + joystick.Horizontal; } var rotVec = transform.up + _turningHeel * transform.forward; RB.AddTorque(rotVec * _turnPower * sideways, ForceMode.Acceleration); }
public void FixedUpdate() { GetInput(); RB.AddForce(-AirDragCoeff * RB.velocity * RB.velocity.magnitude); //air drag (quadratic) RB.AddForce(-AirDownForceCoeff * RB.velocity.sqrMagnitude * transform.up); //downforce (quadratic) RB.AddForceAtPosition(-TireDragCoeff * RB.velocity, transform.position); //tire drag (Linear) SetGearRatio(); SetRPM(); ApplySteer(); ApplyTorque(); TractionControl(); SetMileTick(); }
void FixedUpdateDrag(ICollProvider collProvider, Vector3 waterSurfaceVel) { // Apply drag relative to water var pos = RB.position; Vector3 undispPos; if (!collProvider.ComputeUndisplacedPosition(ref pos, _samplingData, out undispPos)) { // If we couldn't get wave shape, assume flat water at sea level undispPos = pos; undispPos.y = OceanRenderer.Instance.SeaLevel; } var _velocityRelativeToWater = RB.velocity - waterSurfaceVel; var forcePosition = RB.position + _forceHeightOffset * Vector3.up; RB.AddForceAtPosition(Vector3.up * Vector3.Dot(Vector3.up, -_velocityRelativeToWater) * _dragInWaterUp, forcePosition, ForceMode.Acceleration); RB.AddForceAtPosition(transform.right * Vector3.Dot(transform.right, -_velocityRelativeToWater) * _dragInWaterRight, forcePosition, ForceMode.Acceleration); RB.AddForceAtPosition(transform.forward * Vector3.Dot(transform.forward, -_velocityRelativeToWater) * _dragInWaterForward, forcePosition, ForceMode.Acceleration); }
public void FixedUpdate() { if (vehicleController != null) { SteerInput = vehicleController.SteerInput; AccellInput = vehicleController.AccelInput; } //air drag (quadratic) RB.AddForce(-airDragCoeff * RB.velocity * RB.velocity.magnitude); //downforce (quadratic) RB.AddForce(-airDownForceCoeff * RB.velocity.sqrMagnitude * transform.up); //tire drag (Linear) RB.AddForceAtPosition(-tireDragCoeff * RB.velocity, transform.position); //calc current gear ratio float gearRatio = Mathf.Lerp(gearRatios[Mathf.FloorToInt(CurrentGear) - 1], gearRatios[Mathf.CeilToInt(CurrentGear) - 1], CurrentGear - Mathf.Floor(CurrentGear)); if (Reverse) { gearRatio = -1.0f * gearRatios[0]; } //calc engine RPM from wheel rpm float wheelsRPM = (axles[1].right.rpm + axles[1].left.rpm) / 2f; if (wheelsRPM < 0) { wheelsRPM = 0; } // if the engine is on, the fuel injectors are going to be triggered at minRPM // to keep the engine running. If the engine is OFF, then the engine will eventually // go all the way down to 0, because there's nothing keeping it spinning. var minPossibleRPM = IgnitionStatus == IgnitionStatus.On ? minRPM : 0.0f; CurrentRPM = Mathf.Lerp(CurrentRPM, minPossibleRPM + (wheelsRPM * finalDriveRatio * gearRatio), Time.fixedDeltaTime * RPMSmoothness); // I don't know why, but logging RPM while engine is off and we're not moving, is showing // a constant drift between 0.0185 and 0.0192 or so .. so just clamp it down to 0 at that // point. if (CurrentRPM < 0.02f) { CurrentRPM = 0.0f; } //find out which wheels are on the ground foreach (var axle in axles) { axle.isGroundedLeft = axle.left.GetGroundHit(out axle.hitLeft); axle.isGroundedRight = axle.right.GetGroundHit(out axle.hitRight); } //convert inputs to torques float steer = maxSteeringAngle * SteerInput; currentTorque = (float.IsNaN(CurrentRPM / maxRPM)) ? 0.0f : rpmCurve.Evaluate(CurrentRPM / maxRPM) * gearRatio * finalDriveRatio * tractionControlAdjustedMaxTorque; foreach (var axle in axles) { if (axle.steering) { axle.left.steerAngle = steer; axle.right.steerAngle = steer; } } if (HandBrake) { //Make the accellInput negative so that brakes are applied in ApplyTorque() AccellInput = -1.0f; } // No autodrive while engine is off. if (IgnitionStatus == IgnitionStatus.On) { AutoSteer(); } ApplyTorque(); TractionControl(); //shift if need be. No auto shifting while engine is off. if (IgnitionStatus == IgnitionStatus.On) { AutoGearBox(); } //record current speed in MPH CurrentSpeed = RB.velocity.magnitude * 2.23693629f; float deltaDistance = wheelsRPM / 60.0f * (axles[1].left.radius * 2.0f * Mathf.PI) * Time.fixedDeltaTime; odometer += deltaDistance; mileTicker += deltaDistance; if ((mileTicker * 0.00062137f) > 1) { mileTicker = 0; SIM.LogSimulation(SIM.Simulation.MileTick); } /* * // why does this not work :( * float currentRPS = currentRPM / 60.0f; * * float accel = Mathf.Max(0.0f, accellInput); * float angularV = currentRPS * Mathf.PI * 2.0f; * * float power = currentTorque //(rpmCurve.Evaluate(currentRPM / maxRPM) * accel * maxMotorTorque) //Nm * angularV; // Watt * * float energy = power * Time.fixedDeltaTime // w/s * / 1000.0f * 3600.0f; // kw/h * * print("p:" + power + " e:" + energy); * //approximation function for * // https://en.wikipedia.org/wiki/Brake_specific_fuel_consumption#/media/File:Brake_specific_fuel_consumption.svg * // range ~ 200-400 g/kWh * float bsfc = (206.0f + Mathf.Sqrt(Mathf.Pow(currentRPM - 2200, 2.0f) + Mathf.Pow((accel - 0.9f) * 10000.0f, 2.0f)) / 80 + currentRPM / 4500); // g/kWh + + float gasolineDensity = 1f / .75f; // cm^3/g + + float deltaConsumption = bsfc * energy // g * gasolineDensity // cm^3 * / 1000.0f; // l */ // FIXME fix the more correct method above... float deltaConsumption = CurrentRPM * 0.00000001f + currentTorque * 0.000000001f * Mathf.Max(0.0f, AccellInput); // if engine is not powered up, or there's zero acceleration, AND we're not idling // the engine to keep it on, then the fuel injectors are off, and no fuel is being used // idling == non-scientific calculation of "minRPM + 25%". if (IgnitionStatus != IgnitionStatus.On || (AccellInput <= 0.0f && CurrentRPM > minRPM + (minRPM * 0.25))) { deltaConsumption = 0.0f; } consumptionDistance = deltaConsumption / deltaDistance; // l/m consumptionTime = deltaConsumption / Time.fixedDeltaTime; // l/s fuelLevel -= deltaConsumption; float engineWeight = 200.0f; // kg float energyDensity = 34.2f * 1000.0f * 1000.0f; // J/l fuel float specificHeatIron = 448.0f; // J/kg for 1K temperature increase EngineTemperatureK += (deltaConsumption * energyDensity) / (specificHeatIron * engineWeight); float coolFactor = 0.00002f; //ambient exchange if (EngineTemperatureK > ZERO_K + 90.0f && !CoolingMalfunction) { coolFactor += 0.00002f + 0.0001f * Mathf.Max(0.0f, CurrentSpeed); // working temperature reached, start cooling } EngineTemperatureK = Mathf.Lerp(EngineTemperatureK, AmbientTemperatureK, coolFactor); //find current road surface type WheelHit hit; if (axles[0].left.GetGroundHit(out hit)) { traction = hit.forwardSlip; // ground var roadObject = hit.collider.transform.parent == null ? hit.collider.transform : hit.collider.transform.parent; } else { traction = 0f; // air } CurrentSpeedMeasured = ((RB.position - lastRBPosition) / Time.fixedDeltaTime).magnitude; lastRBPosition = RB.position; }