Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by darbotron · Mar 17, 2014 at 02:44 PM · gameobjecteditor-scriptingmonobehaviourfunctionsiterate

how do I generate a drop-down list of functions on scripts attached to a game object?

Hi

I'm writing a property drawer to customise the unity editor GUI for a class I've written.

To make it work the way I would like to I need to be able to generate a drop list of all functions belonging to all instances of monobehaviour derived types that are attached to the same game object.

Clearly making a drop list in a property drawer is pretty trivial.

However, to populate the drop list correctly I need to iterate all components attached to the same gameObject as the component that has the property drawer and generate a list of all (public?) functions exposed by those components.

I also need to be able to use the user's selection in the drop-list to create a delegate to the appropriate function of the appropriate component.

I know this is possible, because the GUI for creating and editing animation events does something like this to allow the user to choose which function to call when the event is triggered, but how this might be accomplished is far from obvious based on the documentation and existing tutorials I've found.

I'm sure I'll work it out myself eventually and if I do I'll post an answer, but I'd appreciate your help if you know how to do this or can point me at sample code...

Alex

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
8
Best Answer

Answer by vexe · Mar 18, 2014 at 11:55 AM

The solution is simple, if you know where to look - it's called Reflection :)

First, you should specify the access level of the methods you're interested in (public, private, etc)

I will give you an answer on how to get the methods, but I will leave the way you store them up to you (you could put them all in one list, you could create a GameObjectEntry, that has a List of MonoBehaviourEntry, which has a List of the methods themselves, etc)

I will just use a list.

The general idea:

1- Get all the MonoBehaviours on your desired gameObject. 2- from each MB, fetch the methods you're interested in.

 var methods = new List<MethodInfo>();
 var mbs = target.GetComponents<MonoBehaviour>();
 var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Default; // BindingFlags is located in System.Reflection - modify these to your liking to get the methods you're interested in
 foreach (var mb in mbs)
 {
   methods.AddRange(mb.GetMethods(flags));  
 }
 
 foreach(var m in methods)
    Debug.Log(m.Name);

That's pretty much it really :D

Here's some helper methods you might be interested in (they're extension methods, so put them in a static class):

 public static class Extensions
 {
 public static List<MethodInfo> GetMethods(this MonoBehaviour mb, Type returnType, Type[] paramTypes, BindingFlags flags)
 {
     return mb.GetType().GetMethods(flags)
         .Where(m => m.ReturnType == returnType)
         .Select(m => new { m, Params = m.GetParameters() })
         .Where(x =>
             {
                 return paramTypes == null ? // in case we want no params
                     x.Params.Length == 0 :
                     x.Params.Length == paramTypes.Length &&
                     x.Params.Select(p => p.ParameterType).ToArray().IsEqualTo(paramTypes);
             })
         .Select(x => x.m)
         .ToList();
 }

 public static List<MethodInfo> GetMethods(this GameObject go, Type returnType, Type[] paramTypes, BindingFlags flags)
 {
     var mbs = go.GetComponents<MonoBehaviour>();
     List<MethodInfo> list = new List<MethodInfo>();

     foreach (var mb in mbs) {
         list.AddRange(mb.GetMethods(returnType, paramTypes, flags));
     }

     return list;
 }
 }

An example of the first one:

 using bf = System.Refleciton.BindingFlags; // put this at the top to reduce some typing
 
 var publicFlags = bf.Instance | bf.Public | bf.Default; // Default could suffice...
 var privateFlags = bf.Instance | bf.NonPublic; // NonPublic alone doesn't suffice when you need to get private methods...
 
 var publicVoidMethods = mb.GetMethods(typeof(void), null, publicFlags); // returns all public methods of the signature void methodName();
 
 var privateSpecialMethods = mb.GetMethods(typeof(Vector3), new[] { typeof(int), typeof(GameObject) }, privateFlags);

and so on...

The second one works very similar to the foreach loop ^ - given a gameObject, it would return the specified methods.

 var methods = go.GetMethods(... similar input to mb.GetMethods ...);

Hope that was helpful.

If you want to learn about reflection, there's no one better than Jamie King on youtube :)

EDIT:

Was missing this:

 public static bool IsEqualTo<T>(this IList<T> list, IList<T> other)
 {
     if (list.Count != other.Count) return false;
     for (int i = 0, count = list.Count; i < count; i++) {
         if (!list[i].Equals(other[i])) {
             return false;
         }
     }
     return true;
 }

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image darbotron · Mar 18, 2014 at 02:54 PM 1
Share

Thanks dude.

I knew the reflection stuff was there and was aware that I'd have to use it to get at the methods - I was really just hoping that there might be existing sample code out there doing more or less what I was trying to to save me muddling through it...

I guess I have most of it now from your answer ;)

I'll totally check out that youtube video too.

If you're interested, once this is done I'll push it into my friend's github repo for sample property drawers: https://github.com/tenpn/ChestOfPropertyDrawers

$$anonymous$$

avatar image vexe · Mar 18, 2014 at 02:59 PM 0
Share

Cool great I'll check it out. Glad I helped. If you need anything more let me know :)

avatar image vexe · Mar 18, 2014 at 03:07 PM 1
Share

Oh crap there's a missing extension method - IsEqualTo - gonna udpate.

avatar image darbotron · Mar 18, 2014 at 08:30 PM 0
Share

another github repo of property drawers - n.b. comments are not in English https://github.com/anchan828/property-drawer-collection

avatar image manny003 · Jan 09, 2015 at 05:55 PM 0
Share

Is this technique possible using UnityScript/Javascript?

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

23 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

in-editor cloning of game objects 1 Answer

What is an instance of a GameObject? 1 Answer

Any way to lock an object from changes in the editor? 4 Answers

Automatically update prefab instance 1 Answer

How to create gameObjects in editor mode 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges