So you wanna do some editor scripting?
I've been following UI Elements since its preview release. Often, I tried from their
examples repo but couldn't dig in so much and this time I'll make a little editor tool walkthrough.
UI Elements
UI Elements is the new kid in town for Unity developers. I give it a go their Recently released some official beginner resources here but I didn't like that uss and uxml stuff. Since I kinda wanted 'database-like editor tool' to hack and learn this, I'll stick with C# Api this time.
Here is the final product.
If you wanna move along, grab the code here.
- Editor window
- Layout with styles
- Add a scroll view
- Add fields
- Save to json
1. Editor window
This part is familiar, create a folder Editor make a script, I'll say ItemEditor and hook up your editor window with MenuItem attribute.
using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; public class ItemEditor : EditorWindow { [MenuItem("Tools/Item Editor")] public static void OpenWindow() { var window = GetWindow<ItemEditor>(); window.titleContent = new GUIContent("Item Editor"); } } Nothing fancy, new menu will pop up in the editor you'll get a fresh empty window.
Next, draw some boxes.
2. Layout with styles
OnEnable call is entry point for my little editor. I'll draw a box for listing items, and another to hold fields for adding a new item.
private void OnEnable() { var root = this.rootVisualElement; var itemsListBox = new Box(); var newItemBox = new Box(); root.Add(itemsListBox); root.Add(newItemBox); } Well, if you look your window again, you won't see anything. So this is where layout involves.
I'll divide my window as 1 portion for list, 3 portion for new item section.
private void OnEnable() { var root = this.rootVisualElement; root.style.flexDirection = FlexDirection.Row; var itemsListBox = new Box(); itemsListBox.style.flexGrow = 1f; itemsListBox.style.flexShrink = 0f; itemsListBox.style.flexBasis = 0f; itemsListBox.style.flexDirection = FlexDirection.Column; var newItemBox = new Box(); newItemBox.style.flexGrow = 3f; newItemBox.style.flexShrink = 0f; newItemBox.style.flexBasis = 0f; root.Add(itemsListBox); root.Add(newItemBox); } First of all, if you haven't heard about flex css like me before,
it may be a good idea to look at how it works, since it uses a flex engine under the hood.
Now I can see my boxes.
https://docs.unity3d.com/Manual/UIE-LayoutEngine.html
And this is the resource that helped me to understand flex.
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Yeah, mo more StartHorizontal or other IMGUI method for layout your window. You won't need OnGUI at all.
3. Add a scroll view
It's so simple, like adding a box I did above.
private ScrollView _scrollView; private void SetupItemList(Box parent) { _scrollView = new ScrollView(); _scrollView.showHorizontal = false; _scrollView.style.flexGrow = 1f; parent.Add(_scrollView); } Also, a label fits good.
private void SetupItemList(Box parent) { var listLabel = new Label("Item List"); listLabel.style.alignSelf = Align.Center; listLabel.style.unityFontStyleAndWeight = FontStyle.Bold; parent.Add(listLabel); _scrollView = new ScrollView(); _scrollView.showHorizontal = false; _scrollView.style.flexGrow = 1f; parent.Add(_scrollView); } 4. Add fields
Let's populate other box with some fields.
Name, rarity and price is simple enough for my little tool.
private void SetupFields(Box parent) { var newItemLabel = new Label("New Item"); newItemLabel.style.alignSelf = Align.Center; newItemLabel.style.unityFontStyleAndWeight = FontStyle.Bold; parent.Add(newItemLabel); var nameField = new TextField("Name: "); var rarityField = new EnumField("Rarity: ", ItemRarity.Common); var priceField = new IntegerField("Price: "); parent.Add(nameField); parent.Add(rarityField); parent.Add(priceField); var saveItemButton = new Button(); saveItemButton.text = "Save Item"; parent.Add(saveItemButton); } Now, I'll create a method for adding items to my scroll view list and when I click
to save item button, it'll get values from fields.
private void CreateListItem(string name) { var itemElement = new VisualElement(); itemElement.style.flexDirection = FlexDirection.Row; itemElement.focusable = true; itemElement.name = name; var remove = new Button(); remove.text = "-"; itemElement.Add(remove); var nameButton = new Button(); nameButton.text = name; nameButton.style.flexGrow = 1f; itemElement.Add(nameButton); _scrollView.contentContainer.Add(itemElement); } I create an empty visual element and afterwards, I add it to scroll view as a whole.
Pretty clean looking and easy comparing between IMGUI api.
Next, I'll create a class ItemData.
[System.Serializable] public class ItemData { public int id; public string name; public ItemRarity rarity; public int price; } Now I can save my item when I hit to save button.
private List<ItemData> _savedItems = new List<ItemData>(); private void SetupFields(Box parent) { var newItemLabel = new Label("New Item"); newItemLabel.style.alignSelf = Align.Center; newItemLabel.style.unityFontStyleAndWeight = FontStyle.Bold; parent.Add(newItemLabel); var nameField = new TextField("Name: "); var rarityField = new EnumField("Rarity: ", ItemRarity.Common); var priceField = new IntegerField("Price: "); parent.Add(nameField); parent.Add(rarityField); parent.Add(priceField); var saveItemButton = new Button(); saveItemButton.text = "Save Item"; saveItemButton.clicked += () => { if (string.IsNullOrWhiteSpace(nameField.value) == false) { var item = new ItemData(); item.id = new Guid().GetHashCode(); item.name = nameField.value; item.rarity = (ItemRarity)rarityField.value; item.price = priceField.value; _savedItems.Add(item); // set default values to clear fields nameField.value = ""; rarityField.value = ItemRarity.Common; priceField.value = 0; CreateListItem(item.name); } }; parent.Add(saveItemButton); } And, I'll add a couple test items. It works!
5. Save to json
Finally I should be able to save and load my data. I'll save my items as a json file in Resources folder.
To handle my json data, I'll create a class and JsonUtility will do the magic.
public class ItemsFile { public List<ItemData> data; } public void LoadData() { var path = Application.dataPath + "/Resources/items.json"; if (System.IO.File.Exists(path)) { var file = System.IO.File.ReadAllText(path); _savedItems = JsonUtility.FromJson<ItemsFile>(file).data; foreach (var item in _savedItems) { CreateListItem(item.name); } } } public void SaveData() { var path = Application.dataPath + "/Resources/items.json"; var itemsFile = new ItemsFile(); itemsFile.data = new List<ItemData>(_savedItems); var itemsFileAsJson = JsonUtility.ToJson(itemsFile); System.IO.File.WriteAllText(path, itemsFileAsJson); } Just load when window opens and save when you hit save button.
Now I have a working sharp looking item editor tool that save data as json.
As a final touch, I'll add removing an item from my list.
private void CreateListItem(ItemData itemData) { var itemElement = new VisualElement(); itemElement.style.flexDirection = FlexDirection.Row; itemElement.focusable = true; var remove = new Button(); remove.text = "-"; remove.clicked += () => { _scrollView.contentContainer.Remove(itemElement); _savedItems.Remove(itemData); SaveData(); }; itemElement.Add(remove); var nameButton = new Button(); nameButton.text = itemData.name; nameButton.style.flexGrow = 1f; itemElement.Add(nameButton); _scrollView.contentContainer.Add(itemElement); } That's all for now.
UI Elements proved me that it's better aproach than
legacy editor scripting and I'll enjoyed without uss and uxml so far :)
If you missed above, grab the code here.
Do you like styling and this flex styling in unity? Let me know what do you think.
Thanks for reading!





Top comments (0)