I want to create a strategy game. When I click the "BuildHouse" button in my action bar I want my manager to register the building that should be built.
All my buildings are components so I try to pass in the building type as a parameter.
My button executes
public void BuildFarm()
{
buildManager.SetBuilding(typeof(Farm)); // Farm is a child of Building
}
Now the BuildManager
knows the type of the building. I tried to iterate through all the building prefabs and pick the one that matches the type.
public class BuildManager : MonoBehaviour
{
[SerializeField]
private GameObject[] buildings;
public void SetBuilding(Type buildingType)
{
GameObject targetBuilding = buildings.Where(currentBuilding => buildingType == currentBuilding.GetComponent<Building>().GetType()).First();
}
}
I don't know if there is a better way to make the BuildManager
get to know what to build. If this idea is bad at all please provide a better way of implementation.
In my opinion filtering by component type is absolutely fine. If you have Farm
and House
components and they are both buildings, it's natural to express it with an inheritance hierarchy.
As concerns using enum
: enums are best at representing simple state or well-specified values that are unlikely to change, eg days of week . There will be no 8th day of week, right? On the other hand, you may want to freely extend the list of available buildings, and each building may implement different game logic. A more natural way to express that is to create a class hierarchy. And when the classes are in place, adding an enum
for the same thing is superfluous.
That said, I'd suggest some improvements in your code.
public void SetBuilding<TBuilding>() where TBuilding : IBuilding
{
GameObject targetBuilding = buildings
.Where(currentBuilding =>
typeof(TBuilding) == currentBuilding.GetComponent<Building>().GetType())
.SingleOrDefault();
if(targetBuilding == null)
{
// throw or log an error here
}
else
{
// instantiate
}
}
If buildingType
is always known at compile-time you can use generics. It makes calls to this method slightly more readable: buildManager.SetBuilding<Farm>();
Notice the where TBuilding : IBuilding
constraint. Make your Farm
and House
classes implement a common interface IBuilding
(it could be a common base class too): class Farm : Component, IBuilding
. By this compiler ensures you can't call something like buildManager.SetBuilding<int>();
SingleOrDefault
ensures there's exactly one such GO. In case there's none or more than 1, it returns null. If that's the case, throw or log an error. I know you are making sure the buildings
array is correct but you should enforce it with code.
I suggest defining an enum
:
enum BuildingType
{
Farm,
House,
...
}
Then you can define a Type
property for Building
:
public class Building
{
...
BuildingType Type { get; set; }
...
}
Then you can call SetBuilding
like this (maybe use a switch
):
public void SetBuilding(BuildingType buildingType)
{
// act according to buildingType
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.