Working around different devices calculating different results?

I am creating a replay system, for a simple physics game, and got it working by saving the player’s input and then playing it back.

It worked perfectly when saved and played back on my machine, to my surprise. But I’m concerned that if the replay were played a different device it would generate different calculations and the replay would not match the original play.

I am thinking differences in calculations might happen because of things like floating point precision.

I read that Unity physics is not deterministic but I am using Unity’s physics calculations only for collisions, the rest of the physics is custom. I could even try to scrap using Unity’s collisions. Also, it is not collison heavy, a collision should happen every few seconds or so.

Is that the case, that different devices generate different results in calculations in this case?
If so, what would be a solution for that? I am thinking of truncating every calculation to a set number of decimal points if floating point precision is the only consideration.

Also, this is for a replay system, not a multiplayer networked game, if that makes a difference.
The game has no intentionally randomly generated content as well.

I appreciate any feedback, thanks.

If it is just replaying already-recorded data, what calculations could lead to different outcomes? And if they differed by a tiny amount, what impact would that have on the replay? Are you sure you are chasing an actual problem?

You’ll need perfect determinism at all points in the chain, even the basic math libraries, to support input-only replay functionality. PhysX (ie. Unity’s physics) has guaranteed determinism on the same machine, same build, different runs but may not be deterministic across platforms, even the differences between Intel and AMD’s floating points may cause issues.

There’s a wealth of information here: Deterministic Rollback/Lockstep
and you may be able to get some inspiration from here: GitHub - mrdav30/LockstepRTSEngine: (WIP) Deterministic, Lockstep RTS Engine

If your game is simple enough, simply record all the positions/rotations/other data every tick and smooth between those instead to save yourself a ton of work.

Thanks for the answer @Kurt-Dekker , sorry if I was not clear. I have started by recording only the inputs, not the Transform or any other variable; so, if the physics calculations moving the Transform differ by a tiny amount it would add to larger and larger differences over time. That is my concern.

But I guess, as your answer implies, and @GroZZleR answered below as well, that it could solve this problem by saving more than only the inputs, as economically as possible, then playing that back. I will look into that now. Appreciate any inputs in that direction as I am not very familiar with optimizing serialization and such demands for saving a number of variables every FixedUpdate. Saving only the inputs was very economic. Thanks again.

Thanks for the reply @GroZZleR , that was very elucidating.

I will follow your suggestion of recording the Transform and other relevant data, it won’t be much more than the Transform and a couple of floats to reproduce the movements precisely.

My concern now is about saving this data every FixedUpdate economically, the game is running at 90fps and ideally I would save every at FixedUpdate. I’m targeting mobile and am worried this would substantially impact performance, but am not experienced with saving data in real time enough to judge, or to optimize for that. I appreciate any ideas on this direction.

Thanks again for the helpful answer.