I am using a component system for certain Objects(just like components in Unity). Each component inheriths from the class Component . The objects then have a list of components.
What I am trying to implement is a GetComponent() method. It returns the component of type T if it exists, otherwise it returns null. Let's say that an Object has the Renderer Component. I want to be able to call the Draw method in the Renderer class:
Object.GetComponent<Renderer>().Draw();
The problem is that when I call this function I get the parent class(of type: Component ) instead of the child class. Because of that, when I try the code above ^^ I get the error; 'Component' does not contain a definition for 'Draw' (...)
Code:
internal abstract class GameObject : Object
{
//Props
public string name;
public GameObject? parent;
public Transform transform
{
get
{
return (parent == null) ? transform : parent.transform;
}
private set
{
transform = value;
}
}
public bool isActive = true;
private List<Component> components = new List<Component>();
//Constructer
public GameObject(string name, GameObject? parent = null)
{
this.name = name;
transform = new Transform(this);
components.Add(transform);
this.parent = parent;
}
public void AddComponent(Component component)
{
components.Add(component);
}
//Method that is not working properly
public Component GetComponent<T>()
{
foreach (Component component in components)
{
if (typeof(T) == component.GetType())
return component;
}
return null;
}
}
}
The return value of the method needs to be T
public T GetComponent<T>()
{
// your code
}
GetComponent<Renderer>().Draw()
is 2 statements
GetComponent<Renderer>()
Draw()
By writing it like so:
// 'component' is of type 'Component' here, not 'Renderer'
var component = GetComponent<Renderer>();
component.Draw();
It's obvious why it doesn't work with your current code and why it does with the updated one.
PS I'd personally also add a constraint to make sure we can only GetComponent<T>
with types that actually are components, like so:
public T GetComponent<T>() where T : Component
{
}
With the where
we're forcing compile time checks that this method can only be called with types that inherit from Component
Instead of returning Component
, return T
. Also, use is
for type checking and casting:
public T GetComponent<T>() where T : Component
{
foreach(var component in components)
{
if(component is T value) return value;
}
return default;
}
BTW, what if you have two components of the same type? You might want to consider using Linq's OfType<T>()
here instead of a foreach
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.