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 AndyP · Jun 23, 2012 at 08:56 AM · custom-inspectorserializedpropertycustom-editorserializedobject

Custom editor: How to initialise a new array element?

I'm trying to make a simple track editor that uses a Bezier Path to generate a 3d mesh for a friend's racing game. The track data is an array of custom TrackDataPoint objects which store the position, tangent and other properties of each point on the track. Here is the TrackData and TrackDataPoint class code (I removed update functions of TrackData and all the "using" stuff to keep it compact here):

[System.Serializable] public class TrackDataPoint : MonoBehaviour { Vector3 position = Vector3.zero; Vector3 tangentDir = Vector3.right; float tangentWeightIn = 1.0f; float tangentWeightOut = 1.0f; }

[System.Serializable] public class TrackData : MonoBehaviour { public TrackDataPoint[] points; }

In my editor class, I am able to get a custom editor displaying, get a the list of points and get each point into a SerializedProperty object, however, I cannot figure out how to get the data into the list of TrackDataPoints stored in TrackData (points). I can add a new point using the small editor interface I made, but it is not initialized, so just appears as an empty space when I try to display it.

[CustomEditor(typeof(TrackData))] public class TrackDataEditor : Editor { private SerializedObject trackData; private SerializedProperty points;

 void OnEnable () {
     trackData = new SerializedObject(target);
     points = trackData.FindProperty("points");
 }
 
 public override void OnInspectorGUI () {
     trackData.Update();
     //draw GUI for each point
     for (int i = 0; i < points.arraySize; ++i) {
         EditorGUILayout.BeginHorizontal();
 
         GUILayout.Label(i + ":", GUILayout.MaxWidth(20.0f));
         SerializedProperty dataPoint = points.GetArrayElementAtIndex(i);
         EditorGUILayout.PropertyField(dataPoint, true);
 
         EditorGUILayout.EndHorizontal();
     }
     
     EditorGUILayout.BeginHorizontal();
     if (GUILayout.Button("Add point")) {
             points.array Size++;
                     // NOW WHAT!? :)    
     }
     EditorGUILayout.EndHorizontal();        

     trackData.ApplyModifiedProperties();
 }

}

How can I create a new TrackDataPoint and assign it to the empty array element from my editor script? If points happens to be a list of standard types, such as Vector3s, this happens automatically. As it is, I get new elements added to the array, but they are empty and display as a drop box for prefabs. If I remove the : MonoBehaviour from TrackDataPoint nothing shows up. Ideally I'd like to display a custom editor per point by having another editor for TrackDataPoint. Is this possible?

Comment
Add comment · Show 3
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 whydoidoit · Jun 23, 2012 at 09:00 AM 0
Share

And there is some reason, in the future, why you need this custom GUI? - Because the standard GUI would edit your objects in an array without and allow you to add ones...

avatar image AndyP · Jun 23, 2012 at 12:58 PM 0
Share

It's not actually something I desperately need to do, as displaying the points in the inspector is not something that will make for a nice editing experience. I will add an interactive editor in the scene view to make things easy. However, I don't like not knowing how to do things so I am trying to learn.

Also, the standard editor shows an empty array. I can't initialize new objects - I have to drag them in from a prefab, which is definitely NOT the way I want to add them.

avatar image leegod · Feb 03, 2014 at 01:56 PM 0
Share

Hi, I have question, at unity 4.3.4(newest), this work?

I applied this way to my script, but met error of

ArgumentOutOfRangeException: Argument is out of range. Parameter name: index

at this point,

showTrackDataPoint[i] = EditorGUILayout.Foldout(showTrackDataPoint[i],"Point #"+i); if(showTrackDataPoint[i]){

1 Reply

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

Answer by delstrega · Jun 23, 2012 at 12:34 PM

Here's the working version using List:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 [System.Serializable]
 public class TrackDataPoint : Object{
     public Vector3 position = Vector3.zero;
     public Vector3 tangentDir = Vector3.right;
     public float tangentWeightIn = 1.0f;
     public float tangentWeightOut = 1.0f;
 }
 
 [System.Serializable]
 public class TrackData : MonoBehaviour {
     public List<TrackDataPoint> points;
 }


 using UnityEngine;
 using System.Collections;
 using UnityEditor;
 using System.Collections.Generic;
 
 [CustomEditor(typeof(TrackData))]
 public class TrackEditor : Editor {
     
 private SerializedObject trackDataSO;
 private TrackData myTrackData;
 private List<bool> showTrackDataPoint;
     
 void OnEnable () {
     trackDataSO = new SerializedObject(target);
     myTrackData = (TrackData)target;
 }
 
 public override void OnInspectorGUI () {
         trackDataSO.Update();
         
         EditorGUILayout.BeginVertical();
 
         int i = 0;
         
         foreach(TrackDataPoint tp in myTrackData.points){
             showTrackDataPoint[i] = EditorGUILayout.Foldout(showTrackDataPoint[i],"Point #"+i);
             if(showTrackDataPoint[i]){
                     
                 tp.position = EditorGUILayout.Vector3Field("Position:", tp.position);
                 tp.tangentDir = EditorGUILayout.Vector3Field("TangentDir:", tp.tangentDir);
                 tp.tangentWeightIn = EditorGUILayout.FloatField("Tangent Weight In:", tp.tangentWeightIn);
                 tp.tangentWeightOut = EditorGUILayout.FloatField("Tangent Weight Out:", tp.tangentWeightOut);
                 
             }
             i++;
         }
         
         EditorGUILayout.EndVertical();
 
         if (GUILayout.Button("Add point")) {
             myTrackData.points.Add(new TrackDataPoint());
             showTrackDataPoint.Add(false);
         }
         
         if(GUI.changed){
             EditorUtility.SetDirty(target);
             EditorUtility.SetDirty(myTrackData);
         }
               
        trackDataSO.ApplyModifiedProperties();
    }    
 }

The basic idea is to get a reference to the object you are editing by using

myTrackData = (TrackData)target;

That way you can do all the stuff you would normally do with arrays and such and don't have to worry about SerializedProperty at all. So you can add an element by adjusting the array length and adding the new point like you would do outside of the editor. Since you are working on the "target" object, only casted differently, all changes should automatically reflect in the editor.

Hope that points you into the right direction,

delstrega

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 AndyP · Jun 23, 2012 at 12:56 PM 0
Share

Wow, I had no idea that that would work! I'll give it a go. Seems kind of obvious now, but I thought target was a serializedObject and it wasn't possible to access the members at all. I was a little annoyed about that because it's normal to access the object directly in the other editor functions (OnSceneGUI etc.)

I'll convert the array to a list and add some code to make working with it from the editor class easier and then everything should be hunky dory.

Thanks!

avatar image delstrega · Jun 23, 2012 at 01:15 PM 0
Share

Yea, you can access your class as normal just casting "target". But now that I tested the code I posted it must say that it won't work like that. I'll try to fix the bugs and edit my answers to reflect the changes. Stay tuned ;)

avatar image AndyP · Jun 23, 2012 at 01:25 PM 0
Share

Tested it and you're right! It works perfectly. I spent so long looking at the docs for SerializedProperty and SerializedObject and completely overlooked the target parameter of Editor. DOH!

avatar image delstrega · Jun 23, 2012 at 01:42 PM 1
Share

Haha, I'm glad it's working for you. I spent the last 30 $$anonymous$$utes trying to get the code I to work. Well I edited my above post in case anyone is interested. :)

You're welcome AndyP :D

avatar image fwalker · Feb 06, 2013 at 09:32 PM 0
Share

I have a question. Who actually instanciateS the "points" List in TrackData?

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

8 People are following this question.

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

Related Questions

Cannot convert serializedObject to float 1 Answer

Draw custom Property Field in Custom Editor 1 Answer

Incrementing a SerializedProperty on a per-object basis 1 Answer

Key Events in Hierarchy Window 1 Answer

How do I change inspector values of other game objects using a custom Editor Window 0 Answers


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