- Home /
How can I use a variable with getcomponent<>()?
I want to use a variable to call functions from a script. Here's an example of pseudo-code:
//myString is the name of an existing script. someOperation is what I need help with.
gameObject.GetComponent<someOperaton(myString)>().doSomething();
I've tried using Activator.CreateInstance(Type.GetType(myString)) and it just gives me an error that it doesn't want a method group or scriptable object. OK, how else can I do this, then?
Answer by Bunny83 · Apr 08, 2017 at 01:54 AM
You have to use the System.Type version and not the generic version of GetComponent.
GetComponent(Type.GetType(myString))
Note that GetComponent returns a reference of type "Component". If you need to access specific members of a specific class you have to cast the type into the right type.
Generic parameters are not "variables" and can't be dynamic. Compiled code uses static typing.
edit
From your comments below it seems you might want to use class inheritance. For this you don't need to know the actual type or type name at all. If you use GetComponent with your base class type it will return whatever component is derived from that base class.
For example GetComponent<Renderer>()
will return any component that is derived from "Renderer". So the returned class could be a MeshRenderer, SkinnedMeshRenderer, LineRenderer, SpriteRenderer, ... depending on what component is actually attached to the gameobject. Of course the type of the returned reference is just Renderer so you can't access specific members of the actual type without casting the reference into the actual type.
Instead of a base class you can also use interfaces which is usually better. GetComponent will return any component reference that does implement the given interface. The big advantage when using interfaces is that a class can implement multiple interfaces.
public interface IObjectMovement
{
void Move(Vector3 aDisplacement);
}
public class ConcreteMovement : MonoBehaviour, IObjectMovement
{
public void Move(Vector3 aDisplacement)
{
Debug.Log("Move: " + aDisplacement);
}
}
public class Controller : MonoBehaviour
{
public IObjectMovement movement;
void Start()
{
movement = GetComponent<IObjectMovement>();
}
void Update()
{
movement.Move(transform.forward);
}
}
The general the point of polymorphism is abstraction. That means you can treat a more complext class in an abstract way without knowing the actual used type. The base class or interface just defines "method contracts".
A base class example might look like this:
public class BaseClass : MonoBehaviour
{
public virtual void Move(Vector3 aDisplacement)
{
Debug.Log("BaseClass Move");
}
}
public class DerivedClass : BaseClass
{
public override void Move(Vector3 aDisplacement)
{
Debug.Log("DerivedClass Move");
base.Move(aDisplacement);
}
}
public class Controller : MonoBehaviour
{
public BaseClass movement;
void Start()
{
movement = GetComponent<BaseClass>();
}
void Update()
{
movement.Move(transform.forward);
}
}
Here when you attach a DerivedClass to the gameobject, the call to "Move" inside update will call Move of the DerivedClass.
So just to make sure I understand, you're saying that it's not possible to cast the type into the right type using a variable in Unity?
What is the "right" type to which you want to cast? All you're doing is supplying a string, so all GetComponent can do is return a generic component. If you were to supply the type of component you wanted to retrieve then you wouldn't need to be using the string overload in the first place - just use the (preferable) version of GetComponent<Type>();
Basically, I'm trying to future proof my code. I'm creating a game where I'll have a series of fighters, but I don't know yet what those classes will be called, how many there will be, or even what their exact moveset will be. Virtual classes look like they might be a solution to this problem, but I'm still struggling to understand them. What's the simplest, most efficient way to add new classes as I create them, if I already know that these classes WILL exist at some point?
For example, what would happen if I tried to do this with a virtual class?
var myVariable = GetComponent(myInheritedClassString) as myBaseClass;
myVariable.doSomething();
Would Unity be able to find the inheriting class and properly adjust for its overrides if it's typed as the base class? If I could use a string to get and use the appropriate script for a gameobject, I could basically automate the entire process without having to make any adjustments in the game manager in the future.
Thanks! If I had reward points to give, I'd give them to you. I'm sure I'll make a hundred mistakes trying to implement this, but it looks like exactly what I want.
Answer by CamCreates · Dec 23, 2020 at 04:31 PM
Sorry for necroing this thread, but this answer would've saved me hours of work when I was trying this.
You can do this using reflection with the following code:
using System;
using System.Reflection;
Type.GetType(Name Of Component).GetMethod(Method Name, BindingFlags.Public | BindingFlags.Instance
).Invoke(gameObject.GetComponent(Name Of Component), new System.Object[] {Function parameters});
If you're trying to access a variable, replace GetMethod with GetField. While it is always better to inherit from a base class or interface, there are some situations where that isn't possible.