Deterministic RVOController Results?

I’m attempting to create a turn-based multiplayer game where the inputs (i.e. unit commands) are synced at the beginning of each turn, and clients determine the outcome locally.

I’m using a basic tick-based system for framerate independent timing and using the RVOController/RVOSimulator components to handle unit movement.

Each unit is subscribed to the tick system and on every tick, they are handling movement pretty much the same as in one of the tutorial examples:

    private void TickSystem_OnTick(object sender, EventArgs e)
    {
        if (_path == null)
            return;
        
        // Initialize
        float distanceToWaypoint;

        // Waypoint management
        while (true)
        {
            distanceToWaypoint = Vector3.Distance(transform.position, _path.vectorPath[_currentWaypoint]);

            if (distanceToWaypoint < _nextWaypointDistance)
            {
                if (_currentWaypoint + 1 < _path.vectorPath.Count)
                {
                    // Not last waypoint
                    _currentWaypoint++;
                }
                else
                {
                    _reachedLastWaypoint = true;

                    // Last waypoint
                    if (distanceToWaypoint < _completionDistance)
                    {
                        // Complete movement
                        PositionDelta = Vector3.zero;

                        _path.Release(this);

                        _path = null;

                        _onMovementComplete();
                        
                        return;
                    }
                    break;
                }
            }
            else
            {
                break;
            }
        }

        // Calculate movement
        float speed = 3.0f;

        float speedFactor = _reachedLastWaypoint ? Mathf.Sqrt(distanceToWaypoint / _stoppingDistance) : 1f;
        float desiredSpeed = speed * speedFactor;

        _rvoController.SetTarget(_path.vectorPath[_currentWaypoint], desiredSpeed, desiredSpeed * 1.2f);

        float damping = 7.5f;
        PositionDelta = Vector3.Lerp(_lastPositionDelta, _rvoController.CalculateMovementDelta(transform.position, TickSystem.TICK_RATE), damping * TickSystem.TICK_RATE);
        _lastPositionDelta = PositionDelta;

        Debug.Log("Tick: " + TickSystem.Tick + " - " + PositionDelta);

        transform.position += PositionDelta;
    }

However, I’m noticing that, despite the initial state and inputs being the same, the resulting position delta for each tick can sometimes vary between different players.

I’ve tried it without lerping the position delta as well, with the same results.

Is this simply due to floating point errors from my use of many float variables?

Any other advice on this topic would also be greatly appreciated!

Hi

Sorry for the late reply.

The RVOSimulator will run in the update loop, so it will not be completely deterministic.

But I would strongly recommend not relying on determinism since the system uses floating point operations anyway, and those may differ slightly between different machines even if the code that runs is the same.