Unity基于参数'Type'设置Gameobject

时间:2018-06-03 19:48:03

标签: c# unity3d

我想制作一款策略游戏。当我点击操作栏中的“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知道要构建什么。如果这个想法很糟糕,请提供更好的实施方式。

2 个答案:

答案 0 :(得分:2)

在我看来,按组件类型过滤绝对没问题。如果您有FarmHouse个组件并且它们都是建筑物,那么使用继承层次结构来表达它是很自然的。

关于使用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
        }
    }
  1. 如果在编译时始终知道buildingType,则可以使用泛型。它使得对此方法的调用更具可读性: buildManager.SetBuilding<Farm>();

  2. 请注意where TBuilding : IBuilding约束。让您的FarmHouse类实现一个公共接口IBuilding(它也可以是一个公共基类):class Farm : Component, IBuilding。通过此编译器可确保您无法调用buildManager.SetBuilding<int>();

  3. 之类的内容
  4. 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
}