love.physics state divergence during fixed time step synchronization
0 reputation · 24 May 2021, 04:16 UTC
0 reputation · 24 May 2021, 04:16 UTC
LÖVE integrates a Box2D wrapper to handle rigid body dynamics, where the simulation state is advanced using love.physics.update(dt). In a networked environment, maintaining synchronization requires consistent state updates across all clients to prevent simulation drift.
While utilizing a fixed time step is a standard approach to mitigate instability and tunneling, the underlying Box2D implementation may still exhibit divergence across different hardware architectures or compiler versions. This creates uncertainty when attempting to implement a deterministic lockstep or state-synchronization system.
love.physics wrapper provide any internal mechanisms to enforce cross-platform determinism?The love.physics wrapper does not provide internal mechanisms to enforce cross-platform determinism. Because it wraps Box2D, it is subject to the floating-point inconsistencies inherent in different CPU architectures, compiler optimizations, and operating systems. Even with a fixed time step, identical inputs on different machines may result in slightly different floating-point results, leading to simulation drift over time.
Since love.physics does not provide a native "snapshot" or serialization function for the entire world, you must manually iterate through the physics bodies to synchronize state. To ensure exact recovery, you must synchronize both the linear and angular components of every active body.
The recommended approach for state synchronization is as follows:
love.physics.World.(x, y) and angle (theta).(vx, vy) and angular velocity (omega).body:setPosition(x, y) and body:setLinearVelocity(vx, vy), followed by body:setAngle(theta) and body:setAngularVelocity(omega).To minimize visual jitter during synchronization, avoid snapping positions every frame. Instead, implement linear interpolation (lerp) between the current local state and the authoritative server state.
-- Example: Manual state capture for a single body
local state = {
x = body:getX(),
y = body:getY(),
angle = body:getAngle(),
vx = body:getLinearVelocityX(),
vy = body:getLinearVelocityY(),
omega = body:getAngularVelocity()
}
This approach assumes you are using a standard LÖVE release (e.g., 11.x) where love.physics maps directly to Box2D. To verify if your divergence is caused by the time step or floating-point drift, run two instances of the game on the same machine with identical inputs; if they diverge, the issue is likely the time step integration. If they only diverge across different hardware, it is a floating-point determinism issue.
Missing Diagnostic: Are you currently using a fixed accumulator for your love.update(dt) loop, or are you passing the raw dt directly into love.physics.update(dt)?
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 24 May 2021, 06:46 UTC
When using love.physics.newWorld, passing false as the third argument disables the internal sleep system. With sleep disabled, bodies never go to sleep, which removes a source of non‑deterministic wake‑up order that can differ across compilers or CPUs. Combined with a fixed dt and identical force application order, this improves cross‑platform repeatability, though floating‑point rounding differences may still cause drift over many steps.