简体   繁体   English

Unity根据参数“类型”设置Gameobject

[英]Unity set Gameobject based on parameter 'Type'

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. 当我单击操作栏中的“ BuildHouse”按钮时,我希望我的经理注册应建造的建筑物。

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. 现在, BuildManager知道了建筑物的类型。 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. 我不知道是否有更好的方法来使BuildManager知道要构建什么。 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. 如果您具有“ Farm和“ House组件,并且它们都是建筑物,那么很自然地用继承层次结构来表达它。

As concerns using enum : enums are best at representing simple state or well-specified values that are unlikely to change, eg days of week . 关于使用enum :枚举最适合表示简单状态或良好指定的,不太可能更改的值,例如一周中的几天 There will be no 8th day of week, right? 一周的第8天没有,对吧? 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. 而且当这些类就位时,为相同的事情添加一个enum是多余的。

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
        }
    }
  1. If buildingType is always known at compile-time you can use generics. 如果在编译时始终知道buildingType则可以使用泛型。 It makes calls to this method slightly more readable: buildManager.SetBuilding<Farm>(); 它使对该方法的调用更具可读性: buildManager.SetBuilding<Farm>();

  2. Notice the where TBuilding : IBuilding constraint. 注意where TBuilding : IBuilding约束。 Make your Farm and House classes implement a common interface IBuilding (it could be a common base class too): class Farm : Component, IBuilding . 使您的FarmHouse类实现一个通用的接口IBuilding (它也可以是一个通用的基类): class Farm : Component, IBuilding By this compiler ensures you can't call something like buildManager.SetBuilding<int>(); 通过此编译器,确保您无法调用诸如buildManager.SetBuilding<int>();类的东西buildManager.SetBuilding<int>();

  3. SingleOrDefault ensures there's exactly one such GO. SingleOrDefault确保只有一个这样的GO。 In case there's none or more than 1, it returns null. 如果不超过1,则返回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. 我知道您要确保buildings数组正确,但是您应该使用代码强制执行。

I suggest defining an enum : 我建议定义一个enum

enum BuildingType
{
    Farm,
    House,
    ...
}

Then you can define a Type property for Building : 然后,您可以为Building定义Type属性:

public class Building
{
    ...
    BuildingType Type { get; set; }
    ... 
}

Then you can call SetBuilding like this (maybe use a switch ): 然后,您可以像这样调用SetBuilding (也许使用switch ):

public void SetBuilding(BuildingType buildingType)
{
    // act according to buildingType
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM