I have a question about spawning a player in an authoritative multiplayer game. Do I need to spawn the player on both the client’s and the server’s machines, or only on one of them and if only on one, which should it be and why?
each player needs to be spawned on each connected player ( server = player )
in an authoritative setup the server would spawn the players and give the controll to the concerning player
Yes, that’s what I though at the beginning Thanks.
Am, sorry to write for this here, but I don’t want to make another topic for that. I have a problem with the cameras - if a client connects to the server and gets spawned, the server’s player camera will become the client’s one.
I tried this in the beginning, but didn’t work:
if(Player.owner != Network.player) this.gameObject.active = false;
What can I do about this problem ?
i used this :
owner = player;
if(player==Network.player)
{
enabled=true;
cam = GameObject.Find("Main Camera");
sf = cam.GetComponent(SmoothFollow);
sf.target = this.transform;
sf.enabled = true;
Well, I disabled the camera components and put this code:
if(Player.owner == Network.player){
enabled = true;
weaponsCamera.enabled = true;
camera.enabled = true;
}
The server’s player is OK and the cameras work with it, but if a client connects, the client’s cameras won’t activate
The server’s camera becomes the camera, that should be the client’s camera, so the server takes control over the new spawned player.
Hmm, what about spawning different prefabs on the owner’s machine and the other players’?
The problem is how will the code know if that’s the player, that will be the owner and if this is another player?
This code here will spawn a prefab and then set it’s numeration, so I will be able to check if this player is my own one. But how can I check this before spawning anything?
function OnServerInitialized(){
Spawn(Network.player);
}
function OnPlayerConnected(connectedPlayer: NetworkPlayer) {
Spawn(connectedPlayer);
}
function Spawn(connectedPlayer : NetworkPlayer){
var playerNumber : int = parseInt(connectedPlayer +"");
var playerTransform : Transform = Network.Instantiate(playerObject, transform.position, transform.rotation, playerNumber);
var playerNetworkView : NetworkView = playerTransform.networkView;
playerNetworkView.RPC("PlayerSetup", RPCMode.AllBuffered, connectedPlayer);
}
try using networkView like so
if (networkView.isMine)
{
enabled = true;
}
this check if the network view is controlled by this object.
heres another one by using networkView to disable or enable cameras to have them controlled by the correct object / player. (not tested)
if (networkView.isMine) //if the networkView is controlled by this object
{
if (mainCamera) // if the main camera exists
{
mainCamera.camera.enabled = true; //enable the camera
}
}
else
{
mainCamera.camera.enabled = false; // else disable it if not
}
if (!networkView.isMine) // just to make sure that this object does not control the other object
{
enabled = false;
}
just remember to use networkView when doing things like rotating or moving.
Cheers.
Thanks for this it looked promising, but I tried it and still nothing. I have two options - to enable the camera by default and then check if isMine and if it’s not - disable it, the other one is the opposite. Both don’t work however. The client’s camera continues to not activate and the server’s camera, becomes the client’s camera. My camera DOES have a network view component.
if(networkView.isMine){
weaponsCamera.enabled = true;
camera.enabled = true;
}
I can’t believe I can’t fix such thing… :X
oh, you mind posting the whole script that you are using? myabe i can take a look at it.
Sure, but here’s something new:
I just changed my spawning method with the one I mentioned above
The onwer prefab is the player with the cameras, hud scripts and other stuff and the other prefab is just a cube with the player’s script (no cameras):
So the Spawner script is this:
var playerObject : GameObject;
var playerObjectThird : GameObject;
private var playerTransform : Transform;
function OnServerInitialized(){
Spawn(Network.player);
}
function OnPlayerConnected(connectedPlayer: NetworkPlayer) {
Spawn(connectedPlayer);
}
function Spawn(connectedPlayer : NetworkPlayer){
var playerNumber : int = parseInt(connectedPlayer +"");
if(networkView.isMine)
playerTransform = Network.Instantiate(playerObject, transform.position, transform.rotation, playerNumber);
else playerTransform = Network.Instantiate(playerObjectThird, transform.position, transform.rotation, playerNumber);
var playerNetworkView : NetworkView = playerTransform.networkView;
playerNetworkView.RPC("PlayerSetup", RPCMode.AllBuffered, connectedPlayer);
}
Now, there’s no way there will be two cameras in one instance of the game, because only the person who’s playing gets the camera, the other prefab, that is spawned on everyone else’s machines does not have a camera. Yet, still my player spawns and the server gets his camera… I’m thinking it could be because I’m running two instances of the game on the same machine (I connect to 127.0.0.1). I deleted the code that enables/disables the camera, because in a case like this I wouldn’t need it, because no camera is actually spawned on the other machines. So this is the main code now.
After spawned, the RPC calls the function PlayerSetup in the player, which is this one:
@RPC
function PlayerSetup(player : NetworkPlayer){
owner = player;
}
The camera is parented to the player’s object.
i dont think its because of you using the same machine as that is possible. i can see that your scripts are a bit complicated and missing a whole lot of functions that are needed for the connection and spawning the player. i’ll see what i can do and try to get a bit of script done for you later.
Thank you very much for your time!
I was reading the M2H networking tutorial and some topics about this in the internet, but seems I haven’t understood it correctly. Networking has got to be the most complicated thing in Unity for me.
Alright, I figured out why my script keeps spawning the player prefab with the camera on both machines:
if(networkView.isMine)
playerTransform = Network.Instantiate(playerObject, transform.position, transform.rotation, playerNumber);
else playerTransform = Network.Instantiate(playerObjectThird, transform.position, transform.rotation, playerNumber);
Network.isMine will always be true. Now I have an idea for fixing this, but I’m not sure if it’s a nice one…actually two ideas:
Network instantiate a game object on beginning, which will then instantiate the player.
The other way is when the first person player is spawned, a variable will set it’s state to true and the spawner will check if that variable is false. If it’s false, it will spawn the first person version of the player, if already true (there’s already a first person player on that machine), instantiate the third person prefab.
Alright, I tried the method with the variable, that becomes true once the first person player is spawned and this works great on the server, but not on the client, since the client connects after that and the server has already an instantiated player, the client spawns a third person player for himself and a firstperson for the server’s player, so they kinda switch roles.
Any suggestions ? I’ve been trying to solve this for two days
if(networkView.isMine){
weaponsCamera.enabled = true;
camera.enabled = true;
}
this seems odd, your enabling 2 cameras.
just make sure that the client ( not the server ) disables all the cameras and only enables the one it needs.
Yes, I disable two cameras - I have one camera, that culls the scene, and everything and one that’s for the weapons - they are in a separate layer.
That’s what I was trying to do yesterday, but everything I tried failed. Now my idea is to spawn different player prefabs (and this is really a good solution for me, because the player himself has a lot of components and children, that are not needed when he’s third person. So I’ve been trying to spawn different prefabs - on each machine, there will be only one first person player, which will be controlled by the player, the other players will be third person versions of the player. That’s why I was using that player variable and stuff I wrote in my previous post, but it didn’t work as well (well, it worked for the server, but when the client connects, it spawns a third person version for him on the client’s machine, because the script sees that a first person player is already existing).
Can someone help me out with spawning different prefabs? I think if I do this a lot of problems that will follow will be solved.
i think you should look into m2h’s multiplayer tutorial which i think it includes on how to spawn players?
That’s what I’ve done. I looked in the codes provided and read everything before I started. The problem is that I have my own player scripts and everything. I’m trying to make the structure of my scripts the same as in the tutorial, but still no success.
The tutorial however does not say how to do that spawning of different prefabs on the different machines. So if anyone can help me to do it, this will take care of all my problems and I’d really appreciate it
Hi there.
I have a fully working example of instantiating prefabs across a network and setting a unique owner to it, preventing others from controlling it, but are fully able to see it move and fetch information from it (like character name, etc.).
I can tell you, that using ‘if (networkView.isMine)’ is a poor solution for what you want.
I’m using an authorative server structure, but the clients are calling Network.Instantiate themselves.
If you want to spawn a single prefab that looks differently on each computer, you’re going to have to manually send an RPC that tells each connected client to locally initiate (not Network.Initiate) it, and throw in some RPC calls to synchronize movement. This is not an easy task, and I’ve not done this myself since I’ve never had the need for it.
My working code builds on spawning the same looking prefab on each connected and future connecting client as they connect using Network.Instantiate.
- Client calls Network.Instantiate.
- Client sends an RPC directed toward the spawned object’s networkview, but buffered to every player, telling that he owns the object and therefore can control it.
- Script on object receives RPC about who owns it, and sets the owner variable to the player’s Network ID.
- Using if (owner == Network.player) checks, it tells the difference between all the other clients and the owner himself.
My code is massive and complex, and throwing in just a few lines is likely to get you confused because of all the variables and functions that are tied into it. Therefore, it may look quite messy at first sight - until you copy it into your script editor and clean up the code by removing what you don’t need.
But hey, have a look at the key functions in another thread where I actually pasted it:
http://forum.unity3d.com/threads/66724-Players-cannot-see-other-players-(Unity-2.6-with-Javascript)?p=428227&viewfull=1#post428227
The code has been rewritten since then to work even better; but the code you’ll find in my post following that URL is fully functional. Just remember to add in the variables yourself, and remove any excess code you obviously don’t need.
Hi! Thank you for your support.
My approach was exactly the same, but the cameras failed to disable.
Spawner sends an RPC:
playerNetworkView.RPC("PlayerSetup", RPCMode.AllBuffered, connectedPlayer);
Player absorbs and set’s a public variable, valled “owner” to connectedPlayer:
@RPC
function PlayerSetup(player : NetworkPlayer){
owner = player;
}
The camera (which is a child of the player) checks:
if (Player.owner != Network.player) {
weaponsCamera.enabled = false;
camera.enabled = false;
}
What happens is that the client’s camera will be disabled and the server will take the camera of the new spawned player. I’ve been trying to figure this out for three days now and I’m starting to get desprate. Wherever I look or whoever I ask, I get the same answer and it is that this should be working, but it’s not. I’d make a prefab with the player and send it, but he has tons of objects and stuff attatched to it, that it’s not going to work and I’ll have to archive the whole project.
Here, you have done the same thing:
if (Network.isClient owner == Network.player) { // Client code (owner of this entity)
enabled = true;
cam.enabled = true;
camScript = cam.GetComponent("Camera_UnderwaterControl");
camScript.enabled = true;
Debug.Log("Shared_EntityControl: " + enabled);
}
How come it works with your code and mine does not? Just to remind - I have a network view component on the player.
Okay. After a lot more trying I managed to fix that problem and now everything’s fine with the cameras. Thank you all for your time!