I create buildings and they have child Text objects that will reflect the building level.
The Problem:
What can I use to store the buildings a player has built so the data can be persisted?
I've looked at Lists, but when I upgrade a building, how would I update the list so that particular building has its new level reflected?
I'm working on a dictionary so I can update the key with the new value (level) but running into a problem with the keys and names. If I have lets say 10 "Farms" and try to add them to the dictionary, even though they have different properties, I get an error that I have a duplicate.
Currently I am learning how to persist that data through scenes;
GameManager.CS
public class GameManager : MonoBehaviour
{
public static Dictionary playerBuilt = new Dictionary();
public void SaveState()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/EmpireGame", FileMode.Open);
SaveClass sc = new SaveClass()
{
food = Player.food.amount,
buildingList = playerBuilt
};
bf.Serialize(file, sc);
file.Close();
}
}
[Serializable]
class SaveClass
{
public int food, wood, iron, stone;
public Dictionary buildingList = new Dictionary();
}
Building.CS
public abstract class Building : MonoBehaviour, IUpgradable {
public int ID;
//level this building is
public Text levelText;
public int level = 0;
//starting cost to amplify the upgrade cost
public int foodBase, woodBase, ironBase, stoneBase;
//Upgrade cost
public int foodCost, woodCost, ironCost, stoneCost;
public float BuildingCostPercentage = 5f;
public void UpdateDictionary()
{
if (GameManager.playerBuilt.ContainsKey(this))
GameManager.playerBuilt[this] = level;
else
GameManager.playerBuilt.Add(this, level);
}
}
Note: I have not tested the save function so I expect errors.
Answer
Myself, I'd pull out just the parts of the building I really want to save - ie. those that are unique to this instance of the building. Eg..
[System.Serializable]
public struct BuildingRecord {
public BuildingType type;
public Vector2 position;
public int level;
}
Here BuildingType
could be an enumeration, or a reference/index to a Type Object, or even just a string key - whatever will help you look up the appropriate source assets like a prefab when you want to spawn this building back into the game when you load from your save file.
Your Building
can have a method like so...
public BuildingRecord GetRecord() {
return new BuildingRecord(){
type = this.type,
position = (Vector2)transform.position,
level = this.level
};
}
Then your save function can simply iterate over a list of Building
component instances that you've maintained all along, or fetched on demand with FindObjectsOfType
and make a simple serializable array of them:
BuildingRecord[] SaveBuildings(IList buildings) {
var records = new BuildingRecord[buildings.Count];
for(int i = 0; i < records.Length; i++)
records[i] = buildings[i].GetRecord();
return records;
}
On deserialization, you can pass each record to a factory method to look up the right prefab using the type information, spawn it at the given position, and initialize it to the given level.
No comments:
Post a Comment