How should I store a player's resources (RTS type game)?

I’m having a little trouble figuring out the best way to store players variables. Right now I have a prefab that has a ‘ResourceGUI’ attached to it; this keeps track of that player’s resources. Now, a new player prefab is created whenever a server is initialized or joined.

var newPlayer = Network.Instantiate (Player, new Vector2 (0, 0), Quaternion.identity, 0); = "Player" + playerIDNum;

A script attached to the prefab increases the playerIDNum in the start function:


Okay, so what happens is I create a server and everything works well with that player. However, I have trouble when there are more than one players. The first player prefab appears as ‘Player1’ as expected, and debugging tells me that the next player ID should be Player2. However, because network does not update string, the prefab appears simply as ‘Player.’ This creates a problem, because when you purchase a new unit, I find your resources with this code:

	string playerName = "Player" + server.playerIDNum + "(Clone)";
	Debug.Log (playerName);
	resourceGUI = GameObject.Find (playerName).GetComponent<ResourceGUI> ();

Again, the debug says that the playerName is indeed Player2, which is correct, however in game the player2 prefab is created as ‘Player.’

I’ve been trying to figure out a way around this, and am having trouble. I was thinking to have a ‘PlayerID’ object in the game, with a script containing only a matrix of strings. When a new player is created, the new playerID is added to the matrix. When a unit is purchased, I’ll find ‘PlayerID,’ and look up the ID with the number stored in the script. However, I’d still run into the same problem. Should I attach each player’s resources to this one script?

I noticed that unity has dictionary and list commands. Should I be using these?

Yeah, I’d use a dictionary. You could use the player object itself or the id as the key to the resources.

You’d initialize dictionary when the game starts, adding a new entry for each player and initializing all the values to defaults and send them down the wire. This provides easy lookups, like so:

// checks if the player has enough of a resource to buy a thing
public bool CanBuyAThing(Thing thing)
    var gold = manager.GetGoldForPlayer(playerId);
    return gold > thing.price;

// in Manager class
public int GetGoldForPlayer(string playerId)
    // if you would rather an exception be thrown, don't check this first
    if (dictionary.ContainsKey(playerId))
        return dictionary[playerId].gold;
    return 0;

It sounds as if your code = "Player" + playerIDNum;

isn’t even running. If it were, your player’s name would have SOME number after it, and not just be “Player”. In the worst case, you’d have multiple players all called Player1 (assuming playerIDNum is an int).

I know this doesn’t answer “the best way”, but it might be a clue as to why your current way isn’t working.