Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
0
Question by CherryPicker · Sep 19, 2018 at 01:16 PM · editoreditor-scriptingeditorguieditorguilayouteditorscript

Recreate default editor look manually without base.OnInspectorGUI [UnityEditor]

I am trying to create my own custom editor. But I wanted to start with recreating the default editor look without using the base.OnInspectorGUI method.

I managed it somewhat, with 2 main issues.

1) I cannot recreate the greyed out "Script" horizontal line + it points to the target object rather than open the script in editor when clicked

2) My toggles do not work. I can click on them but they don't toggle on and off.

alt text

Here is the snippet of my new custom editor

 using UnityEditor;
 
 [CustomEditor(typeof(LineScript))]
 public class LineScriptCustomEditor : Editor
 {
  public override void OnInspectorGUI()
     {
         LineScript myTarget = (LineScript)target;
 
         //base.OnInspectorGUI();
 
         LineScript lineScript_Editor = myTarget.GetComponent<LineScript>();
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PrefixLabel("Script");
         lineScript_Editor = (LineScript)EditorGUILayout.ObjectField(lineScript_Editor,typeof(LineScript),false);
         EditorGUILayout.EndHorizontal();
 
         GameObject triggerOfInfoPanel_Editor = myTarget.GetComponent<LineScript>().triggerOfInfoPanel;
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PrefixLabel("Trigger Of InfoPanel");
         triggerOfInfoPanel_Editor 
             = (GameObject)EditorGUILayout.ObjectField(triggerOfInfoPanel_Editor, typeof(GameObject),true);
         EditorGUILayout.EndHorizontal();
 
         GameObject popupScriptHolder_Editor = myTarget.GetComponent<LineScript>().PopupScriptHolder;
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PrefixLabel("Popup Script Holder");
         myTarget.GetComponent<LineScript>().PopupScriptHolder
             = (GameObject)EditorGUILayout.ObjectField(popupScriptHolder_Editor, typeof(GameObject), true);
         EditorGUILayout.EndHorizontal();
 
         myTarget.GetComponent<LineScript>().widthFirst = EditorGUILayout.Toggle("Width First", false);
         myTarget.GetComponent<LineScript>().DebugDirections = EditorGUILayout.Toggle("Debug Directions", false);
         myTarget.GetComponent<LineScript>().DebugLinePositions = EditorGUILayout.Toggle("Debug Line Positions", false);
         myTarget.GetComponent<LineScript>().DebugEdgePoints = EditorGUILayout.Toggle("Debug Edge Points", false);


Here are the relevant parts in the Line Script

 public class LineScript : MonoBehaviour
 {
     public GameObject triggerOfInfoPanel;
     public GameObject PopupScriptHolder;
     public bool widthFirst;
     public bool DebugDirections;
     public bool DebugLinePositions;
     public bool DebugEdgePoints;
 
  ....

Any idea how to fix 2 issues I have ?

combined.png (22.8 kB)
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

2 Replies

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

Answer by Bunny83 · Sep 19, 2018 at 09:36 PM

Actually you have several issues in your script. First of all all those GetComponent calls are unnecessary and actually create more errors than they might solve. "myTarget" is already a reference to the LineScript that this editor is editing. Using GetComponent might actually return the wrong script in case there are several scripts on the same gameobject. As i said the GetComponent call is completely unnecessary anyways.


Next is your editor only supports single object editing. The "target" variable was the old way how custom inspectors were written. Usually you would use the SerializedObject / SerializedProperty instance(s) that the editor is providing. The SerializedProperty class represents an iterator through all serializable values of an object including sub classes. Though if you really want to manually implement every field yourself, go ahead.


About your concrete issues. First of all the script field does not reference the script instance but the MonoScript instance that implements the class. You can use MonoScript.FromMonoBehaviour to get the reference to the MonoScript asset which implements the given MonoBehaviour.


You can make any GUI control "disabled" (grayed out) by setting GUI.enabled to false before you draw it. Keep in mind to set it back to true after drawing it since this is a state that affects all controls. In some cases it might be convenient to use EditorGUI.BeginDisabledGroup / EndDisabledGroup to disable certain controls and automatically restore the enabled state in EndDisabledGroup.


Your toggles don't work because you don't pass in the current boolean state. You always pass in false and assign the result to the variable. You have to do

 myTarget.widthFirst = EditorGUILayout.Toggle("Width First", myTarget.widthFirst);


Finally your editor does not use any Undo registration which also means that the changes your editor may apply to your edited object might not be saved. You might want to have a look at the Undo class and the RecordObject method.


What's exactly the reason you want to implement the whole GUI manually? You may want to have a look at the Editor documentation and the examples.

Comment
Add comment · Show 2 · 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 CherryPicker · Sep 19, 2018 at 09:47 PM 0
Share

Thank you for the answer. I found it hard to find information on this, so this is very useful. I was trying things almost blindly, following some tutorials.

Part of the reason I wanted to recreate it manually was to add space between the "Width First" and other toggles, which I think you can't do if you use base.OnInspectorGUI (I might be wrong about this), the other part was just figuring how this works and with your help I am definitely much closer to that.

I also added extra functionality. When you click the Debug options, the information appears in the editor. I just didn't mention that part cause I solved it.

I'll try work around what you mentioned.

avatar image Bunny83 CherryPicker · Sep 19, 2018 at 11:38 PM 1
Share

Well, Unity has several attributes and decorators already built in. You can add headers, spaces or even set a range of an int or float value.

  • Header - Adds a header above the field

  • Range - Shows a slider which uses the $$anonymous$$ / max values given in the attribute

  • Space - Adds a space before the field

  • TextArea / $$anonymous$$ultiline - Shows a string field as a multiline text area ins$$anonymous$$d of a text field

  • Tooltip - Sets a tooltip for the field


With those you don't need a custom editor at all. If you implement a custom inspector those attributes will only have an effect if you use SerializedProperties and EditorGUILayout.PropertyField. In many cases it may be easier to implement a PropertyDrawer or DecoratorDrawer for specific things. The great thing about them is that you can simply use them whereever you like.

avatar image
0

Answer by CherryPicker · Sep 20, 2018 at 10:15 AM

I just wanted to thank the previous poster for his post. It helped immensely.

I have not applied all the things he mentioned yet. Particularly using Serialize and applying the Undo class / RecordObject method.

However. I applied the previous 3 things he mentioned.

1) Using theMonsoScript instance to get the asset rather than the script instance

2) Using GUI.enabled to gray a field out

3) Making my toggles work

I will post what I did so it helps others in the future.

1) this

 MonoScript lineScriptAsset = MonoScript.FromMonoBehaviour(myTarget);
 lineScriptAsset = (MonoScript)EditorGUILayout.ObjectField(lineScriptAsset, typeof(MonoScript), true);

instead of this

 myTarget = (LineScript)EditorGUILayout.ObjectField(myTarget, typeof(LineScript), true);

2) added these 2 lines

 MonoScript lineScriptAsset = MonoScript.FromMonoBehaviour(myTarget);
         GUI.enabled = false;  //   <---------------------------- this part here
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.PrefixLabel("Script");
         lineScriptAsset = (MonoScript)EditorGUILayout.ObjectField(lineScriptAsset, typeof(MonoScript), true);
         EditorGUILayout.EndHorizontal();
         GUI.enabled = true; // <------------------------------- and this part here

3) this

 myTarget.GetComponent<LineScript>().widthFirst 
 = EditorGUILayout.Toggle("Width First", myTarget.widthFirst);

 myTarget.GetComponent<LineScript>().DebugDirections 
 = EditorGUILayout.Toggle("Debug Directions", myTarget.DebugDirections);

 myTarget.GetComponent<LineScript>().DebugLinePositions 
 = EditorGUILayout.Toggle("Debug Line Positions", myTarget.DebugLinePositions);

 myTarget.GetComponent<LineScript>().DebugEdgePoints 
 = EditorGUILayout.Toggle("Debug Edge Points", myTarget.DebugEdgePoints);

instead of this

 myTarget.GetComponent<LineScript>().widthFirst 
 = EditorGUILayout.Toggle("Width First", false);

 myTarget.GetComponent<LineScript>().DebugDirections 
 = EditorGUILayout.Toggle("Debug Directions", false);

 myTarget.GetComponent<LineScript>().DebugLinePositions 
 = EditorGUILayout.Toggle("Debug Line Positions", false);

 myTarget.GetComponent<LineScript>().DebugEdgePoints 
 = EditorGUILayout.Toggle("Debug Edge Points", false);

And now my editor looks like this and works like the original alt text

Which is almost like the original, except the toggles are not perfectly aligned with the object fields alt text

But it works just like the original (although I am not sure about the RecordObject method as the previous user mentioned, I'll need to look into that).

So thanks to the original poster. It is exactly what I needed. The only question left for now being how to align the toggles and the object field and then it will be perfect.


neweditorlook.png (19.8 kB)
originaleditorlook.png (19.9 kB)
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 Bunny83 · Sep 20, 2018 at 10:20 AM 1
Share

The issue is not that your toggles are not aligned but your object fields are not ^^. The ObjectField method comes with many overloads and one is taking a label, just like the Toggle does. Using a seperate PrefixLabel works a bit different. Pretty much any EditorGUI / EditorGUILayout control has an optional label parameter.


About RecordObject, have you actually tried to change anything with your editor and then close Unity and reopen it? Did the change persist? The way Unity serializes the data has changed a few times in the past. Some changes may persist if you additionally edit something else in the same scene / on the same object that does mark the scene dirty. However directly editing prefabs or scriptable object assets may be a different story.


You may want to read through this page.

avatar image CherryPicker Bunny83 · Sep 20, 2018 at 10:36 AM 0
Share

Thank you. You are correct again. Funny how I thought my toggles were wrong ins$$anonymous$$d of the field.

I corrected it. I now use this

         lineScriptAsset = ($$anonymous$$onoScript)EditorGUILayout.ObjectField("Script", lineScriptAsset, typeof($$anonymous$$onoScript), true);

ins$$anonymous$$d of this

          EditorGUILayout.PrefixLabel("Script");
          lineScriptAsset = ($$anonymous$$onoScript)EditorGUILayout.ObjectField(lineScriptAsset, typeof($$anonymous$$onoScript), true);

And now it works. For comparison. One object field was corrected and doesn't have a prefix label and the other 2 have. One is aligned, the other 2 are not. alt text

avatar image CherryPicker Bunny83 · Sep 20, 2018 at 10:51 AM 0
Share

Also, I did manage to add a space between the toggles just using EditorGUILayout.LabelField(""); But I would like to make the space smaller somehow.

  myTarget.GetComponent<LineScript>().widthFirst = EditorGUILayout.Toggle("Width First", myTarget.widthFirst);
         EditorGUILayout.LabelField("");
         myTarget.GetComponent<LineScript>().DebugDirections = EditorGUILayout.Toggle("Debug Directions", myTarget.DebugDirections);
         myTarget.GetComponent<LineScript>().DebugLinePositions = EditorGUILayout.Toggle("Debug Line Positions", myTarget.DebugLinePositions);
         myTarget.GetComponent<LineScript>().DebugEdgePoints = EditorGUILayout.Toggle("Debug Edge Points", myTarget.DebugEdgePoints);

alt text

avatar image Bunny83 CherryPicker · Sep 20, 2018 at 11:19 AM 1
Share

The layout system of the I$$anonymous$$GUI system has the GUILayout.Space method.

If you have some time and want to learn more about the immediate mode GUI system, have a look at my I$$anonymous$$GUI crash course. If you have other issues you should ask a seperate question. A question should address a single issue. If you're new to UnityAnswers i highly recommend to read through the FAQs

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

130 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 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 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 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 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 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

Custom Editor - Is there any way to detect whether the user is in Prefab editing mode? 1 Answer

Track when the value is changed and get it 0 Answers

Better Unity Event UI 0 Answers

Custom inspector difficulties creating a Box / Group like widget 1 Answer

Setting custom amount of space between elements in a custom inspector with EditorGUILayout ? 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