I have a simple LAN topology with a server and say three clients,
-client
server -client
-client
(they are not literally "players")
The three clients communicate to the server various information. Of course just using [Command]
calls.
However they are "all the same". The same few calls are made.
(The server knows which one has sent the info, from the ID.)
At first, I simply spawned a "player" object, with a script on it with the various [Command]
calls.
each client has an abstract player object
it is spawned by the NetworkManager in the usual way
However.
It turns out, the server only "believes" in the last one which connected.
It seems there can only be one "player" in Unity networking.
Really, how do you do that in Unity networking?
Not a complete answer since you already figured it out by yourself.
(You don't have a minimal code example so to be honest I din't completely follow what you are doing... but)
Anyway I would like to share how I usually do it.
On the Player prefab (that is spawned on connect) I put a special component like e.g.
and if needed the same for the other NetworkBehaviour bools like
isServer
etc.Than whenever I have to call a method from another component I also hand it the
PlayerInformation
-> I directly can check if it is the local player e.g.
Now for the part of communicating something back to only the player how called something:
Unfortunately you can not pass a
Component
to commands and Rpc .. but you can passGameObjects
(which have a NetworkIdentity). The NetworkIdentity makes sure the GameObject can be identified over all connected instances.Now only the player who invoked the command should execute the rest of the Rpc method (which usually would be executed by all players)
Doing this keeps things easier and uncluttered - at least for me.
Hope it helps
Answering my own question, for anyone struggling with this:
In fact, you will get one for each player. (Seems obvious once you say it.) There will be a whole pile of these all over the place.
So here:
in fact you will see three of the spawned prefabs.
(Aside: in my example I'm using the server as a "server", not a "host" ..
if you were using the "host" concept, there would be yet another spawned player prefab in there.)
So when you launch the app, only one PC, you make it the server, no connections yet ..
then you launch a second PC, the first client, they connect ... it now looks like this
then you launch a third PC, the second client, they connect ... it now looks like this
.. and so on.
So you have one of the cloned player items for each client. (Again, if you use the "host" concept for the server, that just means there will be another client there on the same physical box as the server.)
Each and every "player" has its own auto-spawned player object - and that is on ALL the devices. Five clients, there will be five auto-spawned player objects on EVERY device (on all six devices).
So what caused the specific bug mentioned?
The hidden surprising difficulty in Unet is the
.isLocalPlayer
concept.Say you do have a script like
Comms
in the example which is on the player prefab, which seems a natural thing to do. Say some other part of the game has to reach out to Comms (to say send a message to the server).In fact, you must find your 'own' player prefab ....
You must find your 'own' player prefab ....
You may invisage having code something like this ..
However this is wrong and debugging will be incredibly erratic.
In fact your code would look like this:
(Note - obviously, you wouldn't Find something like this every time in production, you'd use a singleton or whatever your cup of tea is.)
Consider your script that is "on" the player prefab. In our example it is "Comms.cs".
In most unity examples they envisage you doing stuff "in that script".
In that case it is more intuitive: you just break away if you are not
.isLocalPlayer
.However this is very naive, in practice your zillion scripts around the scene will want to / need to contact your "Comms.cs" and have it do things (since it is the only one that connects to the networking.
In fact,
you do have to find "your"
.isLocalPlayer
at all times.Tricky!
To repeat - Unity doco examples tend to emphasize doing things "on that script". In practice on any large real world project it's not like that, you are "contacting" that script as a central communications resource.