我想制作一款策略游戏。当我点击操作栏中的“BuildHouse”按钮时,我希望我的经理注册应该构建的建筑物。
我所有的建筑都是组件,所以我尝试将建筑类型作为参数传递。
我的按钮执行
public void BuildFarm()
{
buildManager.SetBuilding(typeof(Farm)); // Farm is a child of Building
}
现在BuildManager
知道建筑物的类型。我试图遍历所有建筑预制件并选择与该类型相匹配的预制件。
public class BuildManager : MonoBehaviour
{
[SerializeField]
private GameObject[] buildings;
public void SetBuilding(Type buildingType)
{
GameObject targetBuilding = buildings.Where(currentBuilding => buildingType == currentBuilding.GetComponent<Building>().GetType()).First();
}
}
我不知道是否有更好的方法让BuildManager
知道要构建什么。如果这个想法很糟糕,请提供更好的实施方式。
答案 0 :(得分:2)
在我看来,按组件类型过滤绝对没问题。如果您有Farm
和House
个组件并且它们都是建筑物,那么使用继承层次结构来表达它是很自然的。
关于使用enum
的问题:枚举最适合表示不太可能改变的简单状态或明确指定的值,例如: days of week。一周中没有第8天,对吗?另一方面,您可能希望自由扩展可用建筑物的列表,并且每个建筑物可以实现不同的游戏逻辑。表达它的一种更自然的方式是创建一个类层次结构。当课程到位时,为同一件事添加enum
是多余的。
尽管如此,我建议您对代码进行一些改进。
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
}
}
如果在编译时始终知道buildingType
,则可以使用泛型。它使得对此方法的调用更具可读性:
buildManager.SetBuilding<Farm>();
请注意where TBuilding : IBuilding
约束。让您的Farm
和House
类实现一个公共接口IBuilding
(它也可以是一个公共基类):class Farm : Component, IBuilding
。通过此编译器可确保您无法调用buildManager.SetBuilding<int>();
SingleOrDefault
确保只有一个这样的GO。如果没有或大于1,则返回null。如果是这种情况,请抛出或记录错误。我知道您确保buildings
数组是正确的,但您应该使用代码强制执行它。
答案 1 :(得分:1)
我建议定义一个enum
:
enum BuildingType
{
Farm,
House,
...
}
然后,您可以为Type
定义Building
属性:
public class Building
{
...
BuildingType Type { get; set; }
...
}
然后你可以这样调用SetBuilding
(也许使用switch
):
public void SetBuilding(BuildingType buildingType)
{
// act according to buildingType
}