Get Public Methods from MonoScript
Hi guys.
Is there a way to get all of the custom public Methods (functions), that are in a certain MonoScript? (NOT MonoBehaviour)
Lets say i have a EditorWindow and a field, where i can assign certain MonoScript...So i want to get a list of, only the Public Methods, that i have declared, not all possible methods...
thanks
Answer by AngryTilde · Nov 24, 2015 at 02:01 PM
Ok that makes much more sense then, hmm...
Then you're looking for GetClass() not GetType(), MonoScripts are just representations of the script assets not the actual classes. Change that and it should give you the public methods.
I just found out that this returns the Type of the Class, that is in the $$anonymous$$onoScript... Exactly what i was looking for...
Thanks for all the help.. So if anyone needs to get the Declared Public $$anonymous$$ethods from Selected $$anonymous$$onoScript:
var selObj = Selection.activeObject;
$$anonymous$$onoScript monoScr = selObj as $$anonymous$$onoScript;
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
$$anonymous$$ethodInfo[] mono$$anonymous$$ethods= monoScr.GetClass().Get$$anonymous$$ethods (flags );
Thanks a lot for the help.. :)
ok One last thing, since we're on that page, to finalize the stuff..
How can i call that Class's $$anonymous$$ethods..
As i understand there are 2 ways
1: To make an instance of the Class. Woud that means, that every time i press the button, it will make new instance. If yes, then that's bad idea i guess..
But if i try:
var theClass = Activator.CreateInstance(myType) ; // Create instance of the class
This works, but i can't call the $$anonymous$$ethod, from it.
theClass.$$anonymous$$ethodOne();
returns
does not contain definition for '$$anonymous$$ethodOne'
2: I can reference the Class.
How woud i do that?
Since i allready have the Class i thought, that i can just call it like:
myType.$$anonymous$$ethodOne();
but that doesn't work...
thanks
You'll need to use Invoke ins$$anonymous$$d of calling it directly
So in your case it would look like this:
$$anonymous$$ono$$anonymous$$ethods[i].Invoke(Activator.CreateInstance(myType), null);
Check out the $$anonymous$$ethodBase.Invoke Documentation from $$anonymous$$icrosoft to see how it works.
If you don't want to create a new object each time you'll have to use static methods rather then non-statics as it needs a target (if it's static you can use a null target), or I guess you could pool them... Since it's just for the editor it should be fine either way, garbage collection shouldn't be an issue since it's only a single instance at any one time.
EDIT: Whoops Shoulda scrolled down, saw this was answered.
Answer by fafase · Nov 23, 2015 at 08:18 PM
Using reflection you can do that:
MethodInfo[] methodInfos = obj.GetType().GetMethods();
obj is a reference to whatever type.
I have a script that have 2 methods
public void $$anonymous$$ethodOne()
{
}
public void $$anonymous$$ethodTwo()
{
}
I select that script from the Project Window and then i execute that piece of code:
Object selection = Selection.activeObject;
$$anonymous$$ethodInfo[] methods = selection.GetType().Get$$anonymous$$ethods();
for (int i = 0; i < methods.Length; i++)
{
Debug.Log(methods[i].Name);
}
And i get a lot of stuff returned, but the 2 public methods that i have declared are not in that list.
If i use Flags like this:
BindingFlags flags = BindingFlags.Public;
and then call the Get$$anonymous$$ethods like:
$$anonymous$$ethodInfo[] methods = selection.GetType().Get$$anonymous$$ethods(flags);
I don't get absolutely anything.
So i am playing with this few hours allready and can't figure out, how i can get only these 2 public methods, that i have declared in the Selected script...
Thanks for the help :)
They should be there among all other inherited methods. Because a type contains all of the above types, then it becomes a bit cumbersome to only get the bottom type.
You could either make an interface to only those two methods or you would have to get the base class and remove the methods that it contains.
What is the usage you need? $$anonymous$$aybe there is a better solution.
You know, when you select a UI Button, you can add OnClick Event. And if you add an object there, you can pick the Class and then, which methods you wan to call.
I want to do something similar, but for $$anonymous$$onoScript. So i can have a GUI, that can input $$anonymous$$onoScript and it can expose all Public $$anonymous$$ethods (Only the declared ones).
I found out, that i can get, what i need if i use the name of the Class like this:
void Get$$anonymous$$ethods()
{
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
Type myType = typeof(TestProperties); // Store the Type
$$anonymous$$ethodInfo[] method1 = myType.Get$$anonymous$$ethods (flags);
foreach (var method in method1)
{
Debug.Log(method.Name);
}
}
The Above method is called by a GUI Button. And it returns only "$$anonymous$$ethodOne" and "$$anonymous$$ethodTwo", from the TestProperties $$anonymous$$onoScript. But i use the actual name of the Class...
The problem here is that i want to select other scripts as well and have the code figure out, what is the myType.
I have found out, that if Ins$$anonymous$$d of the script above i use this:
void Get$$anonymous$$ethods()
{
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
UnityEngine.Object selObj = Selection.activeObject;
$$anonymous$$onoScript monoScr = selObj as $$anonymous$$onoScript;
if (selObj.GetType() == typeof($$anonymous$$onoScript))
{
// $$anonymous$$ethodInfo[] method1 = myType.Get$$anonymous$$ethods (flags);
$$anonymous$$ethodInfo[] method1 = selObj.GetType().Get$$anonymous$$ethods();
foreach (var method in method1)
{
Debug.Log(method.Name);
}
}
It actually get's the $$anonymous$$onoScript Type and NOT "TestProperties" type. How can i make a type of TestProperties, from the selected script.
This is what it returns, when the "TestProperties" mono script is selected...
As you can see "$$anonymous$$ethodOne" and "$$anonymous$$ethodTwo" are not here at all...
Answer by vexe · Nov 24, 2015 at 05:34 PM
@instruct9r Hey!
I'm not sure why can't you achieve what you want with just the type.GetMethods(flags) function, where flags = public | instance | declared only. That should give you the methods you need, if you want to get methods up the hierarchy, take out the declared only flag. Keep in mind public alone won't work, you need 'instance' flag along with it. If you want to get very specific methods, you could just annotate those methods with an attribute you create, and then go type.GetMethods(flags).Where(m => m.IsDefined(typeof(MyAttribute)).ToArray();
If you want to invoke a method on an instance created from CreateInstance, you need to get a MethodInfo reference and then use your object on its Invoke function. i.e.
object theClass = Activator.CreateInstance(myType) ;
MethodInfo theFunction = myType.GetMethod("TheFunction", flags);
theFunction.Invoke(theClass, new object[] { arguments, if, any, ... });
Hi @vexe.
$$anonymous$$any thanks for answering..
Now i will explain (At least my logic), why GetType() doesn't return the $$anonymous$$ethods, that i have declared. I might be wrong though. THese are my first steps in the deep waters :)
That's the script that i am selecting..
public class TestProperties : Editor
{
public void $$anonymous$$ethodOne()
{
Debug.Log("$$anonymous$$ethod One Called");
}
public void $$anonymous$$ethodTwo()
{
}
}
If i say selObj.GetType().Get$$anonymous$$ethods
, i think, that doesn't work, because the GetType is returning $$anonymous$$onoScript. And $$anonymous$$onoScript doesn't have my custom methods. What i needed to return a type of "TestProperties ", so i can get the actual $$anonymous$$ethods, that i have declared...
I suppose this is why it didn't worked, but it realy didn't. When i changed to GetClass().Get$$anonymous$$ethods()
, and passed the correct BIndingFlags, it returned only the 2 public methods, that i have declared.
Now. If i use GetClass().Get$$anonymous$$ethods()
- Without Flags it returns a lot more stuff, than the GetType().Get$$anonymous$$ethods()
. So i suppose the Class have more methods, than the Type and they are a lot more...
............... 1:I have a question... What's the difference between Object and object? The second one i can use only if i use "using System"? Is it like a virtual object, that holds some data? If yes does that means i can use it also for holding the methods or it can hold only Classes??
2: If i use "using System;" why i can't declare an Object type? I have to use System.Object
...
$$anonymous$$any thanks for the info, about how to call the $$anonymous$$ethods from the Class... This is insane..
Aaand the final code :)
void Get$$anonymous$$ethods()
{
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
System.Object selObj = Selection.activeObject;
if (selObj.GetType() == typeof($$anonymous$$onoScript))
{
$$anonymous$$onoScript monoScr = selObj as $$anonymous$$onoScript; // Get the selObj as $$anonymous$$onoScript
Type myType = monoScr.GetClass() ; // Store the Type of the Class of the $$anonymous$$onoScript
$$anonymous$$ethodInfo[] class$$anonymous$$ethods = myType.Get$$anonymous$$ethods (flags);
object theClass = Activator.CreateInstance(myType) ;
$$anonymous$$ethodInfo theFunction = myType.Get$$anonymous$$ethod(class$$anonymous$$ethods[0].Name.ToString());
theFunction.Invoke(theClass, new object[]{});
}
}
thanks again for the help...
'object' is short for 'System.Object' - which is the base class in C# where all other types inherit from either directly or indirectly. i.e. when you write:
public class A {}
public class B : A {}
A 'is a' 'System.Object', it implicitly inherits System.Object, as if you said:
public class A : System.Object {}
B is also a 'System.Object' because it inherits from A which in turn inherits System.Object.
I would recommend you download ILSpy, it helps you view the code inside System and Unity's classes, very useful tool for learning. If you do that and inspect 'System.Object', you will see it has no data in it, it just has a bunch of functions like GetHashCode, GetType and ToString. But it's not actually empty, it has a type pointer to point to the type object, and a sync block index that is used when you do 'lock' on an object - This is pretty dumb imo, why would they put that in the root object and force all objects to carry this index? how often do we do 'lock'? not much, why not just have a special type of object that we could lock on and have the sync block index in it? - but whatever, $$anonymous$$$ people...
Now, Unity has its own base object class from which all of its other objects inherit ($$anonymous$$onoBehaviour, Component, Editor, ScriptableObject, Assets, etc) - It gets confusing because now you have System.Object, and UnityEngine.Object - those are different things. UnityEngine.Object is a
System.Object (remember all objects in C# inherit System.Object)
If in a class you have using UnityEngine; and using System; and then you mention the type 'Object', it gets confused cause there's two 'Objects': System.Object and UnityEngine.Object
To avoid this, I personally prefer to add a using statement wherever I use UnityEngine.Object, it goes like:
using UnityObject = UnityEngine.Object;
Which just creates an alias called 'UnityObject' - so now every time I want to use UnityEngine.Object I just use UnityObject, and every time I want to use System.Object I just use the shorthand lower case 'object'.
So that's why when you do reflection on types you get more methods than what you asked for, because all objects inherit System.Object so you get functions like GetType, GetHashCode, GetString, etc.
You cannot inherit directly from UnityEngine.Object, it's just how their API works. You can only inherit $$anonymous$$onoBehaviour, ScirptableObject, Editor and EditorWindow.
Hope that helps!
Great explanation...
using UnityObject = UnityEngine.Object is awesome tip..
Will use that for sure.
$$anonymous$$any thanks for the info..
cheers
Answer by romuloum_unity · Jul 11, 2020 at 08:11 AM
In Unity 2019/2020 you can use this to show methods from gameobject:
System.Reflection.MethodInfo[] method1 = this.GetType().GetMethods();
foreach (var method in method1)
{
Debug.Log(method.Name);
}