Using GetComponent without knowing the script name?
I've seen this asked a few times without any real resolution and I am now thinking that this simply isn't supported. What I would like to do is use GetComponent to assign a variable in the selected object's script but since a number of different objects with different scripts could be selected 'SomeScriptName' is not going to be known.
selectedObject.GetComponent<SomeScriptName>().someVariable = "Example";
I am aware that I can just use SendMessage instead and this may be a better solution all around but after some experimentation I found I can use this to get the name of the script:
Type scriptNameTest = selectedObject.GetComponent<MonoBehaviour>().GetType();
Provided that I have using System;
in there or use System.Type scriptNameTest
That will return 'SomeScriptName' for whichever object is selected. The name of the script can be printed correctly so it seemed logical enough just to do this with that information:
selectedObject.GetComponent<scriptNameTest>().someVariable = "Example";
However that will return an error of 'scriptNameTest' is a variable but is used like a type
.
If I declare scriptNameTest globally rather than locally it will return an error of The type or namespace name 'scriptNameTest' could not be found (are you missing a using directive or an assembly reference?)
So I am assuming that it just isn't possible to use a variable as a class in a GetComponent but I am also quite new to C# so it is quite possible I've just missed something. It seems sort of like an unnecessary limitation to me though. I know there are lots of other ways I could achieve this but it would just be so simple to use this method if it actually worked...
The accepted answer from this post may give you a start in doing what you're trying to to:
http://stackoverflow.com/questions/2107845/generics-in-c-using-type-of-a-variable-as-parameter
I'm just curious why not creating a base class for all those classes that have that variable or implement an Interface handling that variable. both can be used as T for GetComponent() and it's easier to handle.
There was one time I encountered the need to dynamically link unknown scripts. In this case the common factor was that it was one single object looking out to many. I reversed the polarity, so to speak, and simply made those scripts point at the common object, injecting their references in to a List. $$anonymous$$y object could then access them all easily without ever having to have found the objects or their component names.
I posted this prior to implementing any base classes so I can see now that even if this behaviour were possible it probably just wouldn't be very good practice. It is better for each enemy to just have a base Enemy class which can easily be accessed.
It still means then passing variables or functions from that base class to the other enemy script. If I could just get the other enemy script name and use that as the class it would probably be less efficient anyway though.
You are right about it not being good practice.
This is the trouble with the 'finding components' approach. Every case Ive seen has resulted in some inelegant clumpy mess. Its hard to get a truly dynamic approach.
If you know what is guaranteed to be on your object, you can find all components and rule out the ones you expect, leaving you with the names of the other attached scripts.
But these Generic Component methods are often subject to change and a few of them have even been deprecated. This leaves the whole thing feeling rather hacky, anyway.
Answer by Svarr · Apr 02, 2016 at 01:37 AM
As hexagonius said, you could implement an Interface containing a property all these objects should have in common, like an identifier (e.g. enum). You would search for the interface and get any script attached to that object which derives from that Interface.
Then you could just check the property for which script you have found.
Though I'm not sure whether calling methods that are not predefined by the Interface will work.