• 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
1
Question by MogwaiHawk · May 01, 2019 at 11:02 AM · uicustom inspector

UIElements or IMGUI for dynamic custom inspectors

I want to build a custom inspector that renders a list of objects and contains a button. Pressing the button should add a new element to the list. The inspector should render the list including the new element afterwards.

Since the UI is changing (one more element is rendered each time the button is pressed) I am unsure if using UIElements is a good approach. As far as I understood in UIElements you define the UI elements in CreateInspectorGUI, which is called the first time that the inspector is drawn. But you don't define what happens each frame. This is more like the approach in IMGUI.

Would IMGUI be more suitable for this or can I still work with UIElements?

I hope that somebody more into these topics can nudge me in the right direction. :)

Thanks!

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
2

Answer by exploringunity · May 14, 2020 at 02:50 AM

Hey @MogwaiHawk,

Edit: I wrote an in-depth tutorial on how to create dynamic custom inspectors like the one below. You can check it out at Exploring UIElements Part 4: Monster Inspector.


I would definitely recommend UIElements for this. You are correct that you define your UI elements in CreateInspectorGUI. That is also where you can set up event handlers to make your UI dynamic. In your example, you could add a click handler to your button that instantiates some sort of VisualElement and uses the Add function to place the element on your UI. You can use the Remove or Clear functions to get rid of elements that are no longer needed.


Below is a simple, but complete, example I wrote to experiment with the idea. Hopefully it illustrates some of the concepts you are asking about. The idea is that you have a Potion class for your game that has a Title and a list of Effects, and you want a custom inspector for it using UIElements.

Here's the default inspector for our Potion class:

alt text

And a preview of the final result:

A custom inspector using UIElements with dynamic components.


Assets/Potion.cs

 using System.Collections.Generic;
 using UnityEngine;
 
 public class Potion : MonoBehaviour
 {
     public string title;
     public List<string> effects;
 }


Assets/Editor/PotionEditor.cs

 using System.Collections.Generic;
 using System.Linq;
 using UnityEditor;
 using UnityEngine.UIElements;
 
 [CustomEditor(typeof(Potion))]
 public class PotionEditor : Editor
 {
     Potion potion;
     VisualElement effectEditorsContainer;
     Label sizeLbl;
 
     void OnEnable()
     {
         potion = (Potion)target;
         if (potion.effects == null) { potion.effects = new List<string>(); }
     }
 
     public override VisualElement CreateInspectorGUI()
     {
         var mainTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/PotionEditor.uxml");
         var ui = mainTemplate.Instantiate();
 
         sizeLbl = ui.Q<Label>("EffectsListSize");
         effectEditorsContainer = ui.Q("EffectsList");
         var addEffectBtn = ui.Q<Button>("AddEffectBtn");
         addEffectBtn.clicked += AddNewEffect;
 
         RefreshUI();
 
         return ui;
     }
 
     void AddEffect(int idx)
     {
         var effectUI = new PotionEffectEditor(potion, idx, DeleteEffect);
         effectEditorsContainer.Add(effectUI);
     }
 
     void AddNewEffect()
     {
         potion.effects.Add(string.Empty);
         EditorUtility.SetDirty(potion);
         RefreshUI();
     }
 
     void DeleteEffect(PotionEffectEditor effectEditor)
     {
         potion.effects.RemoveAt(effectEditor.idx);
         EditorUtility.SetDirty(potion);
         RefreshUI();
     }
 
     void RefreshUI()
     {
         effectEditorsContainer.Clear();
         foreach (var idx in Enumerable.Range(0, potion.effects.Count))
         {
             AddEffect(idx);
         }
         sizeLbl.text = $"       Size: {potion.effects.Count}";
     }
 }


Assets/PotionEditor.uxml

 <?xml version="1.0" encoding="utf-8"?>
 <engine:UXML
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:engine="UnityEngine.UIElements"
     xmlns:editor="UnityEditor.UIElements"
     xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
 >
   <engine:VisualElement>
     <engine:Style src="PotionEditor.uss" />
     <engine:TextField name="PotionTitle" label="Title" binding-path="title" />
     <engine:Label name="EffectsListHeader" text=" Effects" />
     <engine:Label name="EffectsListSize" text="SIZE: ###" />
     <engine:Button name="AddEffectBtn" text="Add New Effect" />
     <engine:VisualElement name="EffectsList">
     </engine:VisualElement>
   </engine:VisualElement>
 </engine:UXML>


Assets/PotionEditor.uss

 .horizontalContainer { flex-direction: row; }
  #AddEffectBtn { margin: 0 3px 0 20px; }
  #DeleteBtn { color: red; }
  #Effect { flex-grow: 1; }


Assets/PotionEffectEditor.cs

 using UnityEditor;
 using UnityEngine.UIElements;
 using System;
 
 public class PotionEffectEditor : VisualElement
 {
     public Potion potion;
     public int idx;
     Action<PotionEffectEditor> deleteCallback;
 
     public PotionEffectEditor(Potion potion_, int idx_, Action<PotionEffectEditor> deleteCallback_)
     {
         idx = idx_;
         potion = potion_;
         deleteCallback = deleteCallback_;
 
         var template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/PotionEffectEditor.uxml");
         var ui = template.Instantiate();
 
         var effectField = ui.Q<TextField>("Effect");
         effectField.label = $"      Element {idx}";
         effectField.value = potion.effects[idx];
         effectField.RegisterValueChangedCallback(x => UpdatePotionEffect(x));
 
         var deleteBtn = ui.Q<Button>("DeleteBtn");
         deleteBtn.clicked += DeleteEffect;
 
         Add(ui);
     }
 
     void DeleteEffect() { deleteCallback(this); }
 
     void UpdatePotionEffect(ChangeEvent<string> change)
     {
         potion.effects[idx] = change.newValue;
         EditorUtility.SetDirty(potion);
     }
 }


Assets/Editor/PotionEffectEditor.uxml

 <?xml version="1.0" encoding="utf-8"?>
 <engine:UXML
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:engine="UnityEngine.UIElements"
     xmlns:editor="UnityEditor.UIElements"
     xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
 >
   <engine:VisualElement class="horizontalContainer">
     <engine:TextField name="Effect" />
     <engine:Button name="DeleteBtn" text="X" />
   </engine:VisualElement>
 </engine:UXML>


Hope this helps!


default-inspector.png (8.5 kB)
uielements-list-demo.png (8.1 kB)
Comment
Add comment · Show 1 · 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 LarsTheGlidingSquirrel · May 20, 2020 at 06:35 PM 0
Share

Thank you very much for the detailed answer! :)

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

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

How to make lane switching in mobile endless runner using UI buttons? 1 Answer

How to use Text (OpenType .otf) Object as Mask for Image? 0 Answers

How to convert RectTransform position to Screen Position 0 Answers

Canvas with mask and transparent image 1 Answer

iTween ColorFrom & ColorTo with GUI Image 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