Example #1
0
 public void Reset()
 {
     _lastVelocity        = Vector3.zero;
     _acceleration        = Vector3.zero;
     _lastAngularVelocity = Vector3.zero;
     _angularAcceleration = Vector3.zero;
     RigidbodyExtensions.Reset(_rigidbody);
 }
Example #2
0
    private void Correct(IClock fixedClock)
    {
        if (_serverHistory.Count < 1)
        {
            Debug.Log("no server history available");
            return;
        }

        /* Extrapolate last received server state to catch up to client time */

        /* Todo: Save massive amounts of calculation by only simulating 1 correction tick per actual physics frame, you dummy
         * New server state? Do offline sim for however many steps it requires to catch up to local client time instantly.
         * THEN, then you only have to simulate one tick for each real-time physics tick in order to keep up. Until the new server state arrives.
         *
         * So in this method we only tick once
         * In the receive state handler we tick multiple times to catch up to local client time
         */

        var latency = _lastReceivedStateRTT / 2d;
        var timeSinceLastReceivedState = fixedClock.CurrentTime - _lastReceivedStateTimestamp;
        var timeSinceServerState       = latency + timeSinceLastReceivedState;
        var startTime = _lastReceivedStateTimestamp - latency;

        Debug.Assert(timeSinceServerState > 0.0, "timeSinceServerState > 0: " + timeSinceServerState);

        _eulerBody.State = _lastServerState;
        PlayerSimulation.SimulateOffline(_simulation.Config, _eulerBody, t => _inputHistory.Lerp(t), startTime, timeSinceServerState, fixedClock.DeltaTime);
        _correctedState = _eulerBody.State;

        /* Calculate error between corrected server state and current client state */

        var currentClientState = _simulation.UnityBody.State;

        const float maxPosError = 2f;
        const float maxRotError = 45f;

        _posError = Vector3.Distance(currentClientState.Position, _correctedState.Position) / maxPosError;
        _rotError = Quaternion.Angle(currentClientState.Rotation, _correctedState.Rotation) / maxRotError;

        /* Apply corrected state over time, with use of error metrics */

        _posErrorSmooth = Mathf.Lerp(_posErrorSmooth, 0.5f + _posError, 1f / _errorSmoothing * fixedClock.DeltaTime);
        _rotErrorSmooth = Mathf.Lerp(_rotErrorSmooth, 0.5f + _rotError, 1f / _errorSmoothing * fixedClock.DeltaTime);

        var interpolatedState = RigidbodyExtensions.Lerp(
            currentClientState, _correctedState,
            _posErrorSmooth * fixedClock.DeltaTime * _errorCorrectionSpeed,
            _rotErrorSmooth * fixedClock.DeltaTime * _errorCorrectionSpeed);

        if (_applyCorrection)
        {
            interpolatedState.ApplyTo(_simulation.UnityBody.Rigidbody);
        }
    }
Example #3
0
    public ForceAndTorque CalculateForces(VehiclePart part, float angle, Vector3 vehicleWorldVelocity, Vector3 vehicleWorldAngularVelocity)
    {
        Vector3 worldAC           = GetAdjustedWorldAerodynamicCenter(part);
        Vector3 relativePosition  = worldAC - part.Vehicle.Rb.worldCenterOfMass;
        Vector3 partWorldVelocity = RigidbodyExtensions.GetChildVelocity(part.Vehicle.Rb.worldCenterOfMass, vehicleWorldVelocity, vehicleWorldAngularVelocity, worldAC);

        if (part is IAerodynamicPart)
        {
            Vector3 tangentualWorldVelocity = partWorldVelocity - vehicleWorldVelocity;
            WorldTangentualVelocity = tangentualWorldVelocity;
        }

        Vector3 lift             = GetLiftVector(part, angle, partWorldVelocity);
        Vector3 drag             = GetDragVector(part, angle, partWorldVelocity);
        Vector3 aerodynamicForce = lift + drag;
        Vector3 torque           = Vector3.Cross(relativePosition, aerodynamicForce); // τ = r × F.

        return(new ForceAndTorque(aerodynamicForce, torque));
    }
 public void Deserialize(NetBuffer reader)
 {
     State = RigidbodyExtensions.Deserialize(reader);
 }