If an object has a component with a baseclass BaseClass<T>
, calling GetComponent<BaseClass<T>>()
will not return that component. The generic argument seems to throw it off, as a BaseClass
without using generics will correctly return the derived class as a component when GetComponent<BaseClass>()
is called.
Does anyone know a solid workaround for this? The use of a generic arg in this class is somewhat important, so I'd obviously rather not re-write the program's class structure just to accommodate this.
Here's a rough sketch of the classes in question
//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 has this method:
public virtual void Setup(T entity) {}
Which needs to be called shortly after the component is added to a GO.
EDIT:
Effectively what I'm looking to do is the following, without having to hard-code in (I want to actually make use of the generic args I've defined)
if(uiClassObj is typeof(DerivedUIClass1) go.GetComponent<BaseUIClass<EntityType1>>();
else if(uiClassObj is typeof(DerivedUIClass2) go.GetComponent<BaseUIClass<EntityType2>>();
//etc
But considering that there is a component of type BaseUIClass<BaseEntity>
on the go, and the two+ derived classes I'm interested in are defined by DerivedUIClass1<EntityType1>
and DerivedUIClass2<EntityType2>
, the conversion should surely just be implicit?
You can't do what you want the way you want, because Unity doesn't accept components which are generic classes.
I.E., if you have:
public class MyGenericClass<T> : MonoBehaviour {}
you will not be able to add it as a component unless you specify T
via a subclass inheriting from it:
public class MySpecifiedClass : MyGenericClass<[specificType]> {}
So, to solve your problem, you should simply implement a specific interface for everything that should be done when the base class is added as a component. I'll show you an example with float
and int
derived types, you can extend easily to any type you need.
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
}
}
Your components classes
public class BaseClassInt : BaseClass<int> {
private void Awake() {
myEntity = 25;
}
}
public class BaseClassFloat : BaseClass<float> {
private void Awake() {
myEntity = 10.6f;
}
}
Code that gets the interface and calls Setup()
var componentsWithSetup = GetComponents<ISetup>();
foreach (var component in componentsWithSetup) {
component.CallSetup();
}
One workaround would be to use a specific type instead of a generic type at the top level for each type that you need the base class for.
For example:
public class SpecificToFirstTypeClass : BaseClass<FirstType>
{
}
and then use GetComponent<SpecificToFirstTypeClass>
Based on a suggestion from this answers.unity.com question
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With