- Home /
Changing Model and spawning player by RPC
Hi,
I'm making a multiplayer game and I have a problem with my team spawn/ team model change
In my PlayerControl.cs script I do this to spawn and ask for changing model
void OnLoaded()
{
Network.Instantiate(avatar0, transform.position + spawnHeight + blueSpawn, teamRotation, 0);
playerClone = "Player(Clone)";
Player = GameObject.Find(playerClone);
networkView.RPC("chooseTeam", RPCMode.All, Player.name);
Cctrl = Player.GetComponent<CharacterController>();
}
[RPC]
void chooseTeam(string playerName)
{
GameObject skin;
GameObject Player0 = GameObject.Find(playerName);
if (teamStatus)
{
Player0.transform.position = transform.position + spawnHeight + blueSpawn;
Player0.tag = "BlueTeam";
skin = (GameObject)Network.Instantiate(model1, transform.position, transform.rotation, 0);
skin.transform.parent = Player0.transform;
skin.tag = "BlueTeam";
}
else
{
Player0.transform.position = transform.position + spawnHeight + blueSpawn;
Player0.tag = "RedTeam";
skin = (GameObject)Network.Instantiate(model2, transform.position, transform.rotation, 0);
skin.transform.parent = Player0.transform;
skin.tag = "RedTeam";
}
teamStatus = !teamStatus;
}
teamStatus is a bool on the server script, it seems that the host of the server deal correctly with this script but when a new Player connect to the server he is spawned in the same place as the host. What I want is my players to be spawned on the other teamspawn at each chooseTeam call, and then attach to them the skin of the team.
For now only the host see correctly what is happening.
Any idea ?
Answer by Briksins · Jul 22, 2013 at 11:02 AM
It is not very clear where is your server side or client side in the code example you proved, but if whatever you provide is only client side than problem is with your "teamStatus" as it is stored locally and not synced with Server and other clients
I believe your [RPC] call from server "chooseTeam(palyer)" should take not only player, but also teamStatus, and remove your: teamStatus = !teamStatus;
It is fundamentally wrong! Your server should define who belongs to which team, not client.
Well the RPC function is both in the server side script and on the client side script, I'm realy new with RPC and don't realy know how to deal with, I suppose RPC function must be on server and client.
The logic should be:
Client connect to server:
Server and only server decide what $$anonymous$$m is clinet should be
Server respond trough RPC to player with his decision
I didnt work with internal unity networking, ins$$anonymous$$d im using uLink, but anyway. From your script I see than on "OnLoaded" you send RPC call to clients: networkView.RPC("chooseTeam", RPC$$anonymous$$ode.All, Player.name); and each client try to decide to which $$anonymous$$m apply new joined user.
It is not good way of doing so! Ins$$anonymous$$d of it, your newly connected client should:
send this RPC only to server
Server decide to which $$anonymous$$m apply this newly connected user
Server now multicast to all with his decision
Clients shouldn't make decision, they only take server decision as obligate instruction to fallow.
If you want to make game as P2P without authoritative server than your newly joined client will have to make decision based on how many Reds and Blue already in, and than multicast that decision to others and others will take it as obligate instructions to fallow.
it is very not good to allow each client individually decide to which $$anonymous$$m apply new user as each of them could decide different stuff by mistake or by players hack
Decision making only one object (weather it would be server in case of authoritative server or client in case of P2P) - other clients should be just notified about that decision and fallow it as obligate instruction
O$$anonymous$$ so I'll put here my code
Client side: void OnLoaded() { Network.Instantiate(avatar0, transform.position + spawnHeight + blueSpawn, $$anonymous$$mRotation, 0); playerClone = "Player(Clone)"; Player = GameObject.Find(playerClone); networkView.RPC("chooseTeam", RPC$$anonymous$$ode.All, Player.name); Cctrl = Player.GetComponent(); }
[RPC]
void chooseTeam(string playerName)
{
GameObject skin;
GameObject Player0 = GameObject.Find(playerName);
if ($$anonymous$$mStatus)
{
Player0.transform.position = transform.position + spawnHeight + blueSpawn;
Player0.tag = "BlueTeam";
skin = (GameObject)Network.Instantiate(model1, transform.position, transform.rotation, 0);
skin.transform.parent = Player0.transform;
skin.tag = "BlueTeam";
}
else
{
Player0.transform.position = transform.position + spawnHeight + blueSpawn;
Player0.tag = "RedTeam";
skin = (GameObject)Network.Instantiate(model2, transform.position, transform.rotation, 0);
skin.transform.parent = Player0.transform;
skin.tag = "RedTeam";
}
$$anonymous$$mStatus = !$$anonymous$$mStatus;
}
Server Side:
bool $$anonymous$$mStatus = false;
[RPC]
void chooseTeam(string playerName)
{
GameObject skin;
GameObject Player0 = GameObject.Find(playerName);
if ($$anonymous$$mStatus)
{
Player0.transform.position = transform.position + spawnHeight + blueSpawn;
Player0.tag = "BlueTeam";
skin = (GameObject)Instantiate(model1, Player0.transform.position, Player0.transform.rotation);
skin.transform.parent = Player0.transform;
skin.tag = "BlueTeam";
}
else
{
Player0.transform.position = transform.position + spawnHeight + redSpawn;
Player0.transform.rotation = transform.rotation;
Player0.tag = "RedTeam";
skin = (GameObject)Instantiate(model2, Player0.transform.position, Player0.transform.rotation);
skin.transform.parent = Player0.transform;
skin.tag = "RedTeam";
}
$$anonymous$$mStatus = !$$anonymous$$mStatus;
Debug.Log($$anonymous$$mStatus);
nbPlayer++;
}
I'm really new on RPC, I believe you put the same RPCs in both code, if not do you think you could help me with that ?
omg /facepalm :)
do u listen to me or not?
in your case u have authoritative server so only server should decide to which $$anonymous$$m apply new player:
when player connects
//all client code
void OnLoaded(){
networkView.RPC("RequestServerToChooseTeam", RPC$$anonymous$$ode.<server>, Player.name);
}
//server code
[RPC]
RequestServerToChooseTeam(string name)
{
//***
//making decision to which $$anonymous$$m apply new user
//***
//once decided multicast RPC call to all players:
networkView.RPC("addNewPlayer", RPC$$anonymous$$ode.all, Player.name, <player $$anonymous$$m bool>);
//im not sure how to send several params on RPC call
// with native unity Networking
// with uLink u can send object array with parmas
}
//All Clients code:
[RPC]
addNewPlayer(string name, bool $$anonymous$$m)
{
//initialize your player at spawn point of the defined $$anonymous$$m
}
P.S. be nice and and mark answer as accepted if you are happy with it. it is good way tho thanx people who helping you
I thank you to help me on this problem, for now my problem isn't fixed, but thanks to you it is surely going to be fixed. By the way my server isn't a true server it's a Client/Server.
I did what you propose, I'm having bugs for now but I'm marking this answer as accepted because it will probably solve the problem Thanks
You misunderstanding the concept of RPC RPC is the way to call method on remote device. RPC can be send to single target as well as multiple targets
In your case with client/server your RPCs of clients not necessarily should match RPCs on Server
If you calling from client RPC to server: "chooseTeam" it doesn't mean that client obligatory have to have this method implemented unless you want send respond from server to the method with the same name. it is absolutely 2 different environments to do not get confused im recommend you you named RPC with word "Request" once it is RPC from client to server and with word "Response" once it it RPC from server to cleint
//Client.cs:
some$$anonymous$$ethodToSendCallToServer(<params>)
{
networkView.RPC("ClientRequestChooseTeam", RPC$$anonymous$$ode.Server, <params>);
}
[RPC]
serverResponseChooseTeam(<params>)
{
//do stuff
}
//End of Client------------------------------------
//Server.cs:
[RPC]
ClientRequestChooseTeam(<params>)
{
//do stuff
//***
//Replay to Client/Clients
networkView.RPC("serverResponseChooseTeam", RPC$$anonymous$$ode.<Client/All>, <params>);
}
once again, logic with multiple clients and one authoritative server should be like that:
Client send RPC to --> Server Server process it and replay back to --> single client or multiple clients as obligate instruction to fallow
Great ! now the players spawn at the right place. But their skin do not follow them... (They follow them for the actual player but if he look at an other player he just see his skin floating at spawn Point not following the player). It seems that localy the game put the skin on the player but not on the Network.