This topic will be devoted to the creation of an InventoryItem editor, using some of the skills taught in the first section of the RPG: Dialogues and Questing course. It relies on the code taught in the RPG:Inventory Systems course.
What I set out to do was to create an Editor Window capable of editing any InventoryItem or it’s descendants. In the Inventory course, we set things up so that all inventory items, including action items (the basis for spells, potions, or special actions) ultimately descend from a common ancestor, the InventoryItem. I also wanted the editor to show a preview of the tooltip that will be displayed in the game.
The next couple of screenshots will show you our goal, what we are aiming to create.
A WeaponConfig Editor:
A StatsEquippableItemEditor
An ActionItem Editor
All with one editor.
This first post (lesson?) will lay the groundwork to get us started. Many of these early steps will look familiar if you’ve completed the first few lessons of the Dialogues and Quests course, setting up an Editor Window.
We’re going to start by creating a folder under Scripts/Inventories named Editor
In the Unity Assets structure, Editor is a magic word, much like Resources. Where any file in any folder named Resources is guaranteed to be included in your final build, any file in any folder named Editor is automatically stripped from the project in a final build. This is important because Unity basically strips away everything derived from Editor when packaging the build (since you’re not supposed to be able to edit). By putting the EditorWindow class in an Editor folder, this prevents compiler errors.
We’ll create a new C# script and call it InventoryItemEditor. If you’ve been following the course, you should already be familiar with namespaces. Set the namespace to
GameDevTV.Inventories.Editor
.Change the class from deriving from MonoBehavior to EditorWindow
using System;
using UnityEditor;
namespace GameDevTV.Inventories.Editor
{
public class InventoryItemEditor: EditorWindow
{
}
}
We’ll need a Menuitem directive with a ShowEditorWindow method:
[MenuItem("Window/InventoryItem Editor")]
public static void ShowEditorWindow()
{
GetWindow(typeof(InventoryItemEditor), false, "InventoryItem");
}
We’ll need a callback to hook into the OnOpenAsset system that Unity uses to select the correct editor when a file is double clicked.
[OnOpenAsset(1)]
public static bool OnOpenAsset(int instanceID, int line)
{
InventoryItem candidate = EditorUtility.InstanceIDToObject(instanceID) as InventoryItem;
if (candidate != null)
{
return true;
}
return false;
}
And we’ll need to implement OnSelectionChange()
{
var candidate = EditorUtility.InstanceIDToObject(Selection.activeInstanceID) as InventoryItem;
if (candidate == null) return;
selected = candidate;
Repaint();
}
Note that we don’t need to use the OnEnable and OnDisable to hook into Selection.selectionChanged as shown in the course. We can simply implmement the function OnSelectionChange()
. Like Awake()
and Start()
in MonoBehavior, it is called automatically if it exists in an open EditorWindow.
Next, we need to implement the method responsible for drawing the EditorWindow, OnGUI()
void OnGUI()
{
if (!selected)
{
EditorGUILayout.HelpBox("No Dialogue Selected", MessageType.Error);
return;
}
EditorGUILayout.HelpBox($"{selected.name}/{selected.GetDisplayName()}", MessageType.Info);
}
Notice that the first thing we do is check to make sure that there is a selection. If there isn’t, we’ll leave a handy helpbox to inform the user to make a selection and abort the method. After this, it’s safe to assume that selected exists and we can draw the functions.
No InventoryItem
An InventoryItem selected
This does highlight a handy trick to ensure that when we double click on an InventoryItem, the editor has it selected when we open in it. (Simply using OnSelectionChange() doesn’t work when the editor isn’t open because the EditorWindow doesn’t exist yet.
We’re going to add a second ShowEditorWindow() method with a parameter. This one won’t get the preprocessor directive to add a MenuItem.
public static void ShowEditorWindow(InventoryItem candidate) {
InventoryItemEditor window = GetWindow(typeof(InventoryItemEditor), false, "Dialogue Editor") as InventoryItemEditor;
if (candidate)
{
window.OnSelectionChange();
}
}
This method allows us to hook into the selection after the window is created, by calling OnSelectionChanged. Then a simple change to OnOpenAsset will call this new method instead of the one opened by the Main Menu Editor
if (candidate != null)
{
ShowEditorWindow(candidate);
return true;
}
That’s it for this post. In my next reply to the topic, I’ll get things started drawing the basic information about InventoryItem
I’ve forked the RPG code from the course repo to show the changes.
This Post’s GitHub Commit - Created InventoryItemEditor/boilerplate