I am working on a city builder game (nothing serious just for learning purposes), and I am a bit stuck, I think i can say I have intermediate knowledge of unity and c#, but I can’t figure out what would be the best way to manage different buildings and things as such. In my case, the user has a list of buildings with different prices and stats (cost, income, capacity, but they would also have different unique attributes… i think you get it), could you please point me in the right direction?
This is a cool asset that pretty much does it:
(minor edit)
Re-reading your question, perhaps it is more of a general data organization question, in which case the asset isn’t so useful. Generally you would use a list of prices corresponding to prefabs for each thing, or some such organization. There are a fair number of tutorials out there about making inventory systems and other things that display and managed correlated organized list-style data. You might want to start looking at those.
Well I was looking for a way to organize the data, yeah… Let’s say I want to make the list of prices, should i make a class for each price and the corresponding prefab? I guess I will look up some tutorials anyways though…
Data structure organization is pretty wide-open. If you don’t have a lot of experience doing it, you kinda just need to jump in and try a few things out until you begin to get a feel for it. You can also buy a book or read some tutorials on data structures, but that won’t really serve as well as really getting your hands dirty and designing a few things that don’t quite do what you want, understanding how they fall short, and then learning how to fix them.
From my extremely superficial understanding of what you want to do, you probably want a class that contains related information about a building: name, prefab that it looks like, cost to build, area required to build, resources, etc.
To tie it nicely into the Unity world, make the class inherit from a ScriptableObject and you can use the Unity editor’s inspector to set up the data, and create an endless number of building variants.
Here is a sample script that could encode all the information about a building variant:
using UnityEngine;
using System.Collections;
[CreateAssetMenu]
public class BuildingInformation :ScriptableObject
{
public string Description;
public GameObject PrefabForDisplay;
public int CostToBuild;
}
The CreateAssetMenu decorator lets you go anywhere in your project area and right click to create an instance of it. That creates a file on disk with whatever values you want for each field.
Then you can get a list (or array) of those as “Buildable on this level” and go on from there. ScriptableObjects are just assets like anything else and can be used to populate script fields, or loaded with Resources.Load<>() the same as any other asset. It’s pretty powerful stuff that Unity handles with ease.
Here’s the data class we use in City Builder Starter Kit
[System.Serializable]
public class BuildingTypeData
{
public virtual string id { get; set; } // Unique id of the building.
public virtual string name { get; set; } // Human readable name of the building.
public virtual string description { get; set; } // A human readable description of the building.
public virtual string spriteName { get; set; } // The name of the sprite used to represent this building.
public virtual bool isObstacle { get; set; } // If this is the true the building is an obstacle. It can't be built by players only cleared from the scene.
public virtual bool isPath { get; set; } // If this is the true the building is a path. It builds insantly and is handled by the Path Manager.
public virtual int level { get; set; } // Level required to build.
public virtual int cost { get; set; } // How many resources it costs to build this building. For obstacles the cost to clear.
public virtual int buildTime { get; set; } // How long in seconds it takes to build this building. For obstalces the time to clear.
public virtual List<string> allowIds { get; set; } // Ids of the buildings and units that this building allows.
public virtual List<string> requireIds { get; set; } // Ids of the buildings required before this building can be built.
public virtual List<GridPosition> shape { get; set; } // Shape of the building in the isometric grid.
public virtual List<string> activities { get; set; } // Types of activities this building allows.
public virtual RewardType generationType { get; set; } // Type of reward automatically generated by this building. Ignored if generation amount = 0. For obstacles this is reward type for clearing.
public virtual int generationTime { get; set; } // Time to generate the reward.
public virtual int generationAmount { get; set; } // Amount of reward to generate each time interval. For obstacles this is reward amount for clearing.
public virtual int generationStorage { get; set; } // Maximum amount of generated reward to store in this building. Acknowledgement indicator will appear once this value is reached.
public virtual int occupantStorage { get; set; } // The space for holding occupants. Note that occupants size can be variable (for example a building could hold two tigers with a size of 1, but only one elephant whic has a size of 2).
public virtual List<CustomResource> additionalCosts { get; set; } // Additional resource costs for the building.
}
Activities list is an id of activity data which is its own class defining activities like harvest which have their own time, rewards, requirements, etc.
If the custom actions and settings don’t get you enough flexibility you can also extend class, for example:
[System.Serializable]
public class UpgradableBuildingTypeData : BuildingTypeData
{
/**
* The buildings max level.
*/
virtual public int maxLevel { get; set; }
}
There is also BuildingData which is the data for a specific instance of the BuildingType. So for example a BuildingType might have a build time but a Building has a time renaming to finish build.
These classes can be serialised to XML or JSON and stored/sourced locally or from a server.
(Note of course its up to the Building and BuildingManager classes to actually do something with this data.)
Just some ideas that might help…