OnSerialzeNetworkView : stream.isWriting only true for owner

Hello!

Some other users have posted similar issues, but I was wondering if I was going about this problem in the wrong manner.

Quick simple run down of the situation. I have a football (or Soccer if you must :stuck_out_tongue: ) game, with two teams against each other.

Each team has 5 footballers that can be controlled, either by real people (users) or AI if uncontrolled. At ANY POINT during the game, a user can switch which character he is controlling with the AI, so can swap around to be nearer the action ect (not with other users mind, so no AI players means no switching).

So I have a footballer prefab, with a FootballerController script running on each one, this takes input and sorts out movement, actions like kicking ect, either an AI could fire off commands or user input.

I was synching this data up with an OnSerialzeNetworkView function within the script, serializing the transforms and game state that I need.

The issue I have is, who ever is the server creates the whole initial gamestate, so is classed as the “owner” of all the players as they exist regardless of the number of users, and so is the only one who can write state (BitStream.isWriting being true).

The other clients can move their footballers, but they don’t stay in sync as they are never writing the state. The server player can move his character and it appears in sync on all clients as he is writing state fine.

I really like the idea of the OnSerializeNetworkView method and being able to put what data I want to sync and be happy that that is happening, can I just change the “owner” everytime a user changed who they are controlling? Is there another way to sync state without the owner being an issue? Are RPC calls the only real solution? If so would it be foolish to link up an RPC call to all input the user can do, every time they fire off a message to the FootballController script also fire of an RPC (this would happen every time the keystate changes or there is a mouse click)? What about reconnecting/midway joining, I need a way to sync state, but then I guess the Server who owns it all can send that…

Ok that last paragraph got away from me a bit. Is the solution for all users to use RPC calls to move their players on their machine AND on each other? Would it work like so, clients input movement, call an RPC call on their footballer, that is sent over the wire, moves the player on the server machine, which then calls the isWriting section of the OnSerializeNetworkView, or is the OnSerializeNetworkView now only needed for reconnects/midway joining?

On an unrelated note, does “Unity” in any way do anything to resolve conflicts? Is there any documentation on “how” the networking works under the hood, UDP?, TCP?, is there a guarantee that the RPC call will arrive, what about a laggy/late packet, how is that resolved on a client, if at all?

Any thoughts are much appreciated!

-Iain

(I might be away from my computer periodically, so sorry if I don’t reply promptly but I will try and keep an eye on this thread)

on the title: thats correct, aside of the owner nobody can write into a serialized stream.

the communication into the different direction is only possible through RPC. thats something thats often used anyway: players only send requests to the server and the server then applies the request and serializes the changes in form of transform updates etc which then are shared for all players (-> authorative) because if everyone owns his own view you can get into trouble. but it might be of interest in specific cases like low latency shooter / racing for example.

the idea is that the state is always clear → owner changes serialized object → shares the changes with the rest of the game

not

owner changes → someone else changes → which one is right :wink:

So, if all the clients make their moves with RPC calls, when do the effects of their moves appear on their view of the game? Do they wait for a reply from the server that their RPC “worked” and play its effect? Or do all clients assume they are correct and play the RPC call locally?

If they all play the move locally, what if they conflict with other incoming RPC calls on the server? When will they find out the true state of the game?

Will OnSerializeNetworkView send back the changes to the state even after an RPC call has changed the state, thus correcting any RPC call conflicts? (i.e., the clients could receive packets about state that they already agree with)

Let me know if I’m not making this clear, tangling up my thoughts as I type them :S

Indeed you can. But you would apply the current input against a state from the past (“client side prediction” of what the state will be basing on the server state and the users input)

normally that state is 100-200ms old (the unity Networking Example is great in this respect, gives you full code that offers all that out of the box!).
that naturally means that you have a state queue that handles the corresponding timeshift.

There won’t be any incoming rpcs in such an environment.
Players send RPCs to the server
The server processes the input and informs all players about the new state either through an own RPC or network view serialization.

Players only use an RPC to all for login, logout and other “global messages” that the server would only forward anyway.

the serialization will not send anything back.
the owner writes and all other reads (its a one way datastream).

Its the servers job to process the input to generate the new state in such a network setup and write the data to the streams that represent the current state (so a transform or more commonly data from a component)

As hinted above, the official Networking Example you can find on the support -resources area is a great resource to see that in action.

a warning upfront for onserializenetworkview: the amount of data you write must be fixed. you can not send more and then less again, that will not work

Cheers, I think there was some confusion over what I was saying but I lost myself in my own post anyway!

I believe you’ve cleared up what I was asking however so thanks.

Generally my plan of action, keep the current serialization I have that is working (server player can move fine as he is the “owner”) and update the other clients to interact with the server state using RPC calls.

On a side note I’m also thinking on the clients on potentially storing 3 gamestates. One being the last authoritative state received by the server, one being the current local client prediction on what is “about” to happen Xms in the future, and one being the current state that is rendered (an extrapolation some point between authoritative and predicted) and experiment to find a “nice” set-up between how far to predict in the future, and how far to extrapolate from one to the other. May be overkill or unnecessary but I’m intrigued to see the result.

Sounds like an interesting approach.

Will be interesting to see how it works out.

I commonly prefer the way that all players including the server player use RPC to inform the “server”.
That way all can go through the same logic for intrapolation and extrapolation and you can use a unified state system for any user independent on if he hosts or not.

the only difference is that on the server, I don’t do real RPCs, I short circuit them (so call the function directly or use SendMessage). As the new input is processed to generate a future state, it does not make a difference how fast it got through as it is processed and applied basing on its timestamp which is “now” independent on calling it directly or being processed at now + X ms backdating X ms

Hello guys, does this site is still available to the members?