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
3
Question by AlucardJay · Jul 05, 2013 at 02:17 PM · editorcustom-inspectorcustom-editor

Custom Editor : Call a function on multiple selected objects

Learning how to write custom editor scripts.

When I select multiple objects, I can modify a variable and this is assigned to all selected objects, but when I use a custom editor button to call a function, only the first selected object has the function called.

Test scene : Create a new scene, create 2 cubes, create and attach the TestButtons script to both. Now create the TestButtonsInspector and store it in the Editor folder. Symptoms are as above.

TestButtons

 #pragma strict
 
 public var myTransform : Transform;
 public var targetPosition : Vector3;
 
 function Update() 
 {
     LookAtTarget();
 }
 
 function ButtonOne() 
 {
     Debug.Log( "Button One was pressed" );
     
     LookAtTarget();
 }
 
 function ButtonTwo() 
 {
     Debug.Log( "Button Two was pressed" );
     
     transform.LookAt( Vector3.forward );
 }
 
 function LookAtTarget() 
 {
     transform.LookAt( targetPosition );
 }

TestButtonsInspector

 #pragma strict
 
 @CustomEditor( TestButtons )
 @CanEditMultipleObjects
 
 class TestButtonsInspector extends Editor 
 {
     var myTransform : SerializedProperty;
     var targetPosition : SerializedProperty;
     
     var obj : GameObject;
     var objScript : TestButtons;
     
     function OnEnable() 
     {
         obj = Selection.activeGameObject;
         objScript = obj.GetComponent( TestButtons );
         
         myTransform = serializedObject.FindProperty( "myTransform" );
         targetPosition = serializedObject.FindProperty( "targetPosition" );
     }
     
     function OnInspectorGUI() 
     {
         // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
         serializedObject.Update();
         
         
         // myTransform
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PropertyField( myTransform );
         EditorGUILayout.EndHorizontal();
         
         // targetPosition
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PropertyField( targetPosition );
         EditorGUILayout.EndHorizontal();
         
         
         // Editor GUI Buttons
         EditorGUILayout.BeginHorizontal();
         
         if ( GUILayout.Button( "Button One", GUILayout.MinWidth( 80 ), GUILayout.MaxWidth( 250 ) ) )
         {
             //target.ButtonOne();
             //serializedObject.ButtonOne();
             
             //var obj : TestButtons = serializedObject.TestButtons;
             //TestButtons.ButtonOne();
             
             //var go = serializedObject;
             //go.SendMessage( "ButtonOne" );
             
             //this.ButtonOne();
             
             //var obj : GameObject = Selection.activeGameObject;
             //var objScript : TestButtons = obj.GetComponent( TestButtons );
             objScript.ButtonOne();
         }
         
         if ( GUILayout.Button( "Button Two", GUILayout.MinWidth( 80 ), GUILayout.MaxWidth( 250 ) ) )
         {
             //var obj : GameObject = Selection.activeGameObject;
             //var objScript : TestButtons = obj.GetComponent( TestButtons );
             objScript.ButtonTwo();
         }
         
         EditorGUILayout.EndHorizontal();
         
         // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI.
         serializedObject.ApplyModifiedProperties();
     }
 }
Comment
Add comment · Show 2
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 AlucardJay · Jul 06, 2013 at 05:03 AM 0
Share

Hello, is there anybody in there? Just nod if you can hear me. Is there anyone at home?

avatar image Lo0NuhtiK · Jul 06, 2013 at 05:09 AM 2
Share

http://www.youtube.com/watch?v=y7EpSirtf_E

1 Reply

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

Answer by Bunny83 · Jul 06, 2013 at 06:17 AM

Your problem is that you mix two fundamental things together. The Selection class of course holds the actual selection, no matter if it's a gameobject, a prefab, an asset, ... So whatever you select in the Unity editor it will be referenced by the Selection class.

Selection.activeGameObject only holds a reference to the "last" object that has been selected. It works exactly like in Windows. When you select multiple files and grab one of them to drag the files around, the last one you touched is the active one.

Selection.gameObjects holds the list of gameobjects that are selected.


However since you use a custom editor you don't need the selection class at all.

The Editor class has 3 properties that should be enough to work with:

  • target

  • targets

  • serializedObject

target is actually kind of obsolete. It also holds the reference to the component on the active gameobject. target can be useful for single-component editors. For multiple-object editors you have to use the "targets" and the serializedObject which wraps the whole selection at once.

Comment
Add comment · Show 6 · 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 AlucardJay · Jul 06, 2013 at 06:40 AM 0
Share

Thank you for your answer Bunny83. I've been struggling on understanding Serialized Objects. I shall take some time to study the information you have linked to, hopefully I will have that 'Eureka' moment today. Thanks for explaining and defining what I need to look at.

avatar image Bunny83 · Jul 06, 2013 at 07:05 AM 0
Share

The serialized object is just to handle data that can be serialized by Unity. In other words everything that you can adjust setup in the inspector and is saved along with the instance.

UT put a lot of efford into this handy class to make multi-object editing more easy. Ins$$anonymous$$d of handling all the single objects on their own the serialized object treats them as one.

However if you want to call a function on each selected instance you should simply iterate through the targets array

avatar image AlucardJay · Jul 08, 2013 at 11:33 AM 0
Share

Thank you so much for your help. I still have a great amount to learn, but my immediate solution was surprisingly simple using Selection.gameObjects

 #pragma strict
 
 @CustomEditor( TestButtons )
 @CanEdit$$anonymous$$ultipleObjects
 
 class TestButtonsInspector extends Editor 
 {
     var myTransform : SerializedProperty;
     var targetPosition : SerializedProperty;
     
     var obj : GameObject;
     var objScript : TestButtons;
     
     
     function OnEnable() 
     {
         obj = Selection.activeGameObject;
         objScript = obj.GetComponent( TestButtons );
         
         myTransform = serializedObject.FindProperty( "myTransform" );
         targetPosition = serializedObject.FindProperty( "targetPosition" );
     }
     
     
     function OnInspectorGUI() 
     {
         // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
         serializedObject.Update();
         
         
         // myTransform
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PropertyField( myTransform );
         EditorGUILayout.EndHorizontal();
         
         // targetPosition
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PropertyField( targetPosition );
         EditorGUILayout.EndHorizontal();
         
         
         // Editor GUI Buttons
         EditorGUILayout.BeginHorizontal();
         
         var objScript : TestButtons;
         
         if ( GUILayout.Button( "Button One", GUILayout.$$anonymous$$inWidth( 80 ), GUILayout.$$anonymous$$axWidth( 250 ) ) )
         {
             for ( var obj in Selection.gameObjects )
             {
                 Debug.Log( "" + obj.name );
                 
                 objScript = obj.GetComponent( TestButtons );
                 
                 objScript.ButtonOne();
             }
         }
         
         
         if ( GUILayout.Button( "Button Two", GUILayout.$$anonymous$$inWidth( 80 ), GUILayout.$$anonymous$$axWidth( 250 ) ) )
         {
             for ( var obj in Selection.gameObjects )
             {
                 Debug.Log( "" + obj.name );
                 
                 objScript = obj.GetComponent( TestButtons );
                 
                 objScript.ButtonTwo();
             }
         }
         
         EditorGUILayout.EndHorizontal();
         
         
         // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI.
         serializedObject.Apply$$anonymous$$odifiedProperties();
     }
 }
avatar image Bunny83 · Jul 08, 2013 at 12:52 PM 0
Share

Of course it will work, but it's not ment to be used like this ;)

An Editor instance is created to edit the a certain set of objects. Those objects are referenced by the targets array. So the even more easier solution is:

 for ( var obj : TestButtons in targets )
 {
     Debug.Log( "" + obj.name );
     obj.ButtonOne();
 }

The Selection class belongs to the scene-view and what is selected there. Each inspector has it's own reference(s) to the object(s) it is inspecting. Just try your solution, select some objects, lock the inspector and deselect the objects. The inspector will still be active as well as it's targets array but the SceneView Selection will be empty.

avatar image AlucardJay · Jul 08, 2013 at 03:50 PM 0
Share

Wow, I would have never realized. Your comment gave a different perspective and really helped me get closer to understanding what is actually going on. Note closer, not full understanding!

This is my first step in editor GUI. Several of my own built tools have different functions I wish to run in edit mode. $$anonymous$$y previous method was to select a value in an enum and then use context menu ( see my answer here for an example : http://answers.unity3d.com/questions/420154/modify-existing-mass-place-trees-function.html ). I thought it was time to add some buttons, but have been stuck and lost on this for a while. Thanks again for your help, it is has been invaluable and very much appreciated (sounds cliche but its true).

Show more comments

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

17 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

Related Questions

Inspector: custom property with custom type use default editor 3 Answers

Custom editor tags not saving 1 Answer

Custom Inspector Horiztonal Vector2 and Button Spacing 0 Answers

TerrainToolkit build errors 2 Answers

Create Spells through classes in custom editor? 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