Using Random Numbers in Multiplayer Games with non-Authoritative servers


I was trying to synchronize the random numbers between peers in a non-authoritative server. For example, Id like the behavior of enemies (which is modeled with random numbers) to be the same on each machine.

More specifically, the use of the same seed (which guarantees the same sequence on every machine) is not enough since different machines have different computation time and they can never run exactly at the same time.

Also, I intend not to synchronize all the enemies through network views but let their behavior be processed locally.

Please let me know if youve ever done this in your own projects, and if you could share any tips.

Thanks a lot, Paul

The only tip I have: Don't do it that way ;-) ... any logic that's game related should be synchronized via the network. A little "difference" in looks might be processed locally when those differences are acceptable but I wouldn't risk having things run out of sync (e.g. with the random numbers).

What you could probably do if you don't have an authoritative server is to have the clients validate any relevant actions i.e. if client A does something, client B and C "check" if that action was valid. That way, cheaters should be easy to find out about. If you have a little time for lag, you could also implement some sort of "voting" system: each client sends their random number to each other client, then they create the average and send that average to everyone to validate (I'm assuming small-scale multiplayer with maybe 10-20 players at max).

In general, I find using an authoritative server much easier - but obviously that creates the problem that you need to keep the server(s) running.

If you need some kinda behavioural data which is random from game to game then how about pre-calculating a certain amount of data before round starts?

I think of this example as a game where you need some dices.

First, when someone enters the game, they download this "list of dice-roles" which was pre-generated like a deck of cards are shuffled. Then you give each dice its uniq "offset", infact you just keep the offset of the first dice and then pick the following numbers pr. dice, incrementing the offset everytime you request a number.

The first "offset" you get from the sync of the current game and each time you step one forward in the "array of dices roles" you have a random number again. Everyone has the same list, so infact everyone could "lure" the client data transfered (this is why your pre-calc method might give some troubles) but - you would from a "timestamp" have a certain way of know exactly where you are in this "cycle". At the end of the array/list you either can recycle the list and start all over or switch to a new downloaded list, which you can pregenerate on certain keyframes/timestamps.

Like this:

Frame #0 - Pregenerate list of 1000 random numbers. Frame #1 - move 1 Frame #2 - move 2 . . Frame #1000 - Pregenerate list of 1000 random numbers.

If a player enters at frame eg. 743 they still download the numbers, either from 0 to 1000 or just from current frame and up til "next keyframe" and then they are also in the "loop".

I think you should performance test which array sizes would work best for your application/game as a turnbased game wouldn't have any trouble downloading like 2000 numbers, where as a realtime FPS might only have 256 precalculated and downloaded. I dont know for sure, as this is just an idea.

Another approach would be to produce "noise patterns" like in a bitmap, and then download this bitmap and look up the pixel value. Then you can make your random/list with colors in a paint program.

"The only tip I have: Don't do it that way ;-) ... any logic that's game related should be synchronized via the network. A little "difference" in looks might be processed locally when those differences are acceptable but I wouldn't risk having things run out of sync" - Jashan

After a couple of months of frustration due to network desynchronization, I have learned that this is the only solution for my problem since any dynamic activity (enemy movement, etc) can rapidly degenerate into desynchronization even if there is no randomness involved.

At first I wanted to avoid by all means putting a networkView on each enemy in order to keep the network overhead to a minimum. This approach finally led me to implement the exact same system implemented by Unity with the networkViews :) - instead of synchronizing each enemy with its remote replica, I would put a unique ID and send an RPC over the network with the ID as parameter. I have circled around the problem just to get back exactly where I started :)

In short, it is recommended to sync any dynamic activity and the best way to do it is (despite a large amount of problems and errors Unity network views pose themselves) through network Views. Just Put a network view on anything that needs to be thoroughly synched.

Thanks alot guys, especially Jashan :) - I had to learn this the hard way


just do your calculations locally, then send out the rpc with parameters reflecting the random numbers. as long as your synchronized with a network view, all the randomness can happen locally to that gameobject as far as movements, and again when you need it to fire send all that stuff with paramz. i am using the same technique as what you are trying with great success with MY ai.