Keeping track of teams in multiplayer game.

Hi, I have a game based off of Leepo's multiplayer tutorial. I have a deathmatch mode finished but want to add a team mode and am having a very hard time doing so.

I've been trying to have the server keep total control of teams and send updates instead of depending on the AllBuffereds from individual clients. I modified the scoreboard script like this and it seems to be much more accurate.

When a player joins I try to call an RPC function on the server to update the server's playerList array list. The FPSNode contains and added variable team, which will equal 1 or 2. The server will then send a buffered update to all the clients to update their playerLists, but the results are never correct and it is hard to see what is actually happening. A lot of times on the client side all the networkPlayers will equal 0 for all players except the player himself in the playerList, but the server playerList will be 100% correct. And there are no errors in the debuglog, so everything is acceptable.

This is my playerNode:

using UnityEngine;
using System.Collections;

//fpsplayernode script from multiplayer tutorial converted to c#.

public class FPSPlayerNode{

    public string playerName;
    public NetworkPlayer networkPlayer;
    public int team = 0;

    public int kills =0;
    public int deaths =0;

}

These are the key function in my GameSetup script

void Awake() 
{

    playerName = PlayerPrefs.GetString("playerName");

    chatScript = GetComponent<FPSChat>();
    Network.isMessageQueueRunning = true;
    Screen.lockCursor=false;

    if(Network.isServer){

        chatScript.ShowChatWindow();

        MasterServer.RegisterHost(gameName, PlayerPrefs.GetString("serverName"));

    }else if(Network.isClient){

        networkView.RPC ("TellOurName", RPCMode.AllBuffered, playerName);
        networkView.RPC ("TellClientsOurName", RPCMode.AllBuffered, playerName, playersTeamNum);

        chatScript.ShowChatWindow();

        GameObject[] gobjectsc = (GameObject[])FindObjectsOfType(typeof(GameObject));

        foreach (GameObject go in gobjectsc){
            go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver); 
        }

    }else{
        //How did we even get here without connection?
        Screen.lockCursor=false;    
        Application.LoadLevel(6);       
    }

    Network.isMessageQueueRunning = true;
}

[RPC]
//Sent by newly connected clients, recieved by server
public void TellOurName(string name, NetworkMessageInfo info){

    if(Network.isServer){
        int teamNum = 0;
        NetworkPlayer netPlayer = info.sender;

        if (PlayerPrefs.GetString("gameMode")=="Team Death Match"){
            Debug.Log("This is a Team Death Match");

            if (team1Count <= team2Count){
                teamNum = 1;
                team1Count += 1;
                Debug.Log("team 1 = " + team1Count);
                chatScript.addGameChatMessage(name+" joined the red team");
            } else if (team2Count < team1Count){
                teamNum = 2;
                team2Count += 1;
                Debug.Log("team 2 = " + team2Count);
                chatScript.addGameChatMessage(name+" joined the blue team");
            }       
        } else {
            Debug.Log("This is not a Team Death Match");
            chatScript.addGameChatMessage(name+" joined the game");
        }

        networkView.RPC("SetPlayerInfo", RPCMode.AllBuffered, name, netPlayer, teamNum);
    }

}

[RPC] 
public void SetPlayerInfo(string name, NetworkPlayer player, int teamNum){
    playersTeamNum = teamNum;
    playersName = name;
    playersNetPlayer = player;
}

[RPC]
//Sent by newly connected clients, recieved by server
public void TellClientsOurName(string name, int iteamNum,  NetworkMessageInfo info){
    int teamNum = iteamNum;

    NetworkPlayer netPlayer = info.sender;
    if(netPlayer+""=="-1"){
        //This hack is required to fix the local players networkplayer when the RPC is sent to itself.
        netPlayer=Network.player;
    }

    FPSPlayerNode newEntry = new FPSPlayerNode();
    newEntry.playerName=name;
    newEntry.networkPlayer=netPlayer;
    newEntry.team = teamNum;
    playerList.Add(newEntry);
}

I know it looks funky, but I need the player's name in everyone's playerlist during the awake call of the gamesetup script because each player has 3dtext to display above their player that depends on it. Thank if you can offer any advice.

I think what you're running into is that NetworkPlayer only really works on the server. What I used are my own IDs for players that I keep across all instances (clients + server). So I have lookup Dictionaries (Dictionary) and do all synchronization that way, which works very smoothly.

Personally, I'm not a fan of "buffered stuff". It'll probably work nicely if you don't have a server that runs for a long time - but if you do, new clients might get all kinds of "stuff" they're not really interested in. So what I do instead is send one specific client all the data it needs after it connected. Then, everyone who is connected gets updates as necessary. This way I have much more control and it works quite nicely.