- Home /
Network - Balancing Teams
Hello,
I'm working on a multiplayer team game, and I'm struggling to make a player join a certain team, depending how many people are already in the teams. This is so each team is always balanced out.
Before, I just made the player join a random team.
I have two teams, red and blue.
I have a function called 'OnNetworkLoadedLevel' which what lets my players join the game, this is responsible for initiating the player, adding him to a score board, selecting his team colour ... and so on. But for the life of me, I just can't get a simple team balancing function to work.
I tried many methods. The first one was just a simple 'find all the players', and see what team they all are, and figure out what team I then need to be. Anyway, heres my code, hope you can do a better job... I've been looking at this for well over 5 hours now! I've taken out all my attempt at balancing the teams, and I've just left the 'random selection' one in:
function OnNetworkLoadedLevel(){
var randomColour : int;
randomColour = Random.Range(0, 2); //blue - red
var spawnPlayer : Transform;
spawnPlayer = Network.Instantiate(playerPrefab, transform.position, transform.rotation, 0);
//set players colour according to random colour
var playerID : NetworkView = spawnPlayer.gameObject.GetComponent(NetworkView);
networkView.RPC("selectColour", RPCMode.AllBuffered, playerID.viewID, randomColour);
}
@RPC
function selectColour(playerID : NetworkViewID, colourInt : int){
var ID = NetworkView.Find(playerID);
var player = ID.observed.gameObject;
var body = player.gameObject.GetComponent(CharacterMove); //holds the players colour/team
if(colourInt == 0){
colour = "Red";
body.playerBody.renderer.material = playerMaterials[0];
body.myColour = colour;
}
else if(colourInt == 1){
colour = "Blue";
body.playerBody.renderer.material = playerMaterials[1];
body.myColour = colour;
}
}
Like I said, I firstly tried just finding all the players and their teams, and figuring out which team I then need to be in by placing:
var players = GameObject.FindGameObjectWithTag("Player");
for(var playerTeam in players){
var playerColour = playerTeam.gameObject.GetComponent(CharacterMove).myColour;
if(playerColour == "Blue")
blue ++;
else if(playerColour == "Red")
red ++;
}
... in my OnNetworkLoadedLevel, but it never finds anything. Please help me! I am completely stumped!
a 's' is missing to FindGameObjectsWithTag ... but I think this just a typo in your question right?
just set a cont for each $$anonymous$$m if (red > blue ){ blue++}else{red++}
Answer by olliej777 · Aug 24, 2012 at 01:37 PM
Okay,
I've been working around Laurent Victorino answer, and it seems to be working 'so far', (haven't tested it heavily):
function OnNetworkLoadedLevel(){
//Initiate player
var spawnPlayer : Transform;
spawnPlayer = Network.Instantiate(playerPrefab, transform.position, transform.rotation, 0);
//Askes host for a colour/team
var playerID : NetworkView = spawnPlayer.gameObject.GetComponent(NetworkView);
networkView.RPC("WhatTeam", RPCMode.AllBuffered, playerID.viewID);
}
//Host Only
@RPC
function WhatTeam(playerID : NetworkViewID){
if(Network.isServer){
print("Server - Retrieving Player List");
//Pulls all current players colour/team
var playerBoard = gameObject.GetComponent(PlayerBoard);
for(var i = 0; i < playerBoard.playerColours.length; i++){
if(playerBoard.playerColours[i] == "Blue")
blues ++;
else if(playerBoard.playerColours[i] == "Red")
reds ++;
}
var whatColour : String;
if((blues == 0 && reds == 0) || (blues == reds)){
whatColour = "Red";
}
else if(blues > reds){
whatColour = "Red";
}
else if(reds > blues){
whatColour = "Blue";
}
//Initiate colour for player
networkView.RPC("SelectColour", RPCMode.AllBuffered, playerID, whatColour);
}
}
@RPC
function SelectColour(playerID : NetworkViewID, whatColour : String){
print("Selecting colour for player");
var ID = NetworkView.Find(playerID);
var player = ID.observed.gameObject;
var body = player.gameObject.GetComponent(CharacterMove);
if(whatColour == "Red"){
colour = "Red";
body.playerBody.renderer.material = playerMaterials[0];
body.myColour = colour;
print("Colour is RED");
}
else if(whatColour == "Blue"){
colour = "Blue";
body.playerBody.renderer.material = playerMaterials[1];
body.myColour = colour;
print("Colour is BLUE");
}
}
One problem that I think might occur is that is a player leaves the game, it wont deduct from the 'blues' or 'reds' ints.
Answer by lvictorino · Aug 23, 2012 at 08:52 PM
Why don't you simply let the host chose the colour for players?
When a player is initiated he send a RPC to host in order to receive his colour. The host has the list of connected players with colours assigned to every one of them. The host send back a RPC to the new initiated player to set his colour according to the team balancing rules you have defined.
When you try to put your colour counter code in your OnNetworkLoadedLevel your are not sure that networked player have been instantiated yet... so you can't be sure FindGameObjectsWithTag will return you something because it's maybe to soon to do so.