Unity:GetComponent <baseclass <t>&gt; - 这有什么变通方法吗?

时间:2018-03-07 13:47:11

标签: unity3d

如果某个对象的组件包含基类BaseClass<T>,则调用GetComponent<BaseClass<T>>()将不会返回该组件。泛型参数似乎将其抛弃,因为BaseClass不使用泛型将在调用GetComponent<BaseClass>()时正确地将派生类作为组件返回。

有没有人知道这方面的可靠解决方法?在这个类中使用泛型arg有点重要,所以我显然不是为了适应这种情况而不重写程序的类结构。

这是所讨论课程的粗略草图

//the base class that I'd like to be able to fetch the subclasses of using GetComponent
public abstract class BaseUIClass<T> : MonoBehaviour where T :BaseEntity {}

//EntityType1&2 are derived from BaseEntity
public class DerivedUIClass1 : BaseUIClass<EntityType1> {}
public class DerivedUIClass2 : BaseUIClass<EntityType2> {}

BaseUIClass有这个方法:

public virtual void Setup(T entity) {}

在将组件添加到GO后不久需要调用。

编辑:

实际上,我希望做的是以下内容,而无需进行硬编码(我希望实际使用我已经定义的通用算法)

if(uiClassObj is typeof(DerivedUIClass1) go.GetComponent<BaseUIClass<EntityType1>>();

else if(uiClassObj is typeof(DerivedUIClass2) go.GetComponent<BaseUIClass<EntityType2>>();
//etc

但考虑到有一个BaseUIClass<BaseEntity>类型的组件,我感兴趣的两个+派生类由DerivedUIClass1<EntityType1>DerivedUIClass2<EntityType2>定义,转换应该只是暗示?

3 个答案:

答案 0 :(得分:3)

对于您需要基类的每种类型,一种解决方法是在顶级使用特定类型而不是泛型类型。

例如:

public class SpecificToFirstTypeClass : BaseClass<FirstType>
{
}

然后使用GetComponent<SpecificToFirstTypeClass>

基于this answers.unity.com question

的建议

答案 1 :(得分:3)

你不能按照自己想要的方式做你想做的事,因为Unity不接受通用类的组件。

I.E。,如果你有:

public class MyGenericClass<T> : MonoBehaviour {}

除非您通过继承自它的子类指定T,否则您将无法将其添加为组件:

public class MySpecifiedClass : MyGenericClass<[specificType]> {}

因此,为了解决您的问题,您应该简单地为基类作为组件添加时应该完成的所有事情实现特定的接口。我将向您展示一个包含floatint派生类型的示例,您可以轻松扩展到您需要的任何类型。

<强> BaseClass的

using UnityEngine;

public interface ISetup {
    void CallSetup();
}

public class BaseClass<T> : MonoBehaviour, ISetup {
    public T myEntity;

    public void CallSetup() {
        Setup(myEntity);
    }

    private void Setup(T entity) {
        Debug.Log(entity);
        //Your setup code
    }
}

您的组件类

public class BaseClassInt : BaseClass<int> {
    private void Awake() {
        myEntity = 25;
    }
}
public class BaseClassFloat : BaseClass<float> {
    private void Awake() {
        myEntity = 10.6f;
    }
}

获取界面并调用Setup()

的代码
var componentsWithSetup = GetComponents<ISetup>();
foreach (var component in componentsWithSetup) {
    component.CallSetup();
}

答案 2 :(得分:0)

我不敢相信这不起作用,所以我使用标签对其进行了破解,其中 UI 是一个基本的抽象类:

public UI currentUI;

public void GetUI()
{
    foreach (Transform child in transform)
    {
        if (child.tag == "UI Canvas")
        {
            currentUI = child.GetComponent<UI>();
        } 
    }
 }

根据场景,我可能有不同的活动“用户界面”。它可能是主要游戏场景,或菜单场景。现在,我可以通过 LoadUI() 或 HideUI() 等通用/抽象方法与 UI 管理器进行交互。

Tbf,这确实应该由事件处理,但对我当前的项目来说这太过分了。