Inventory Custom Entries

Extend the power of the inventory with adding custom entries to it.

The documentation has moved to: https://mitschmr-studios.io/documentation/api-guides/inventorycustomentries.html

This version will no longer be updated and maintained.

In this tutorial, I want to show you how to extend the Game Creator inventory with custom entries.

Prerequisites

  • Install Unity

  • Install IDE (I use Visual Studio 2019)

  • Import Game Creator

  • Import and enable the Inventory module

Game Creator Inventory

Before we begin, I want to talk a bit about the inventory of Game Creator. It is a module for Game Creator, which allows you to store items in it (as you would expect). It contains an item catalogue (the item store), a types section for the types of items you have, a recipes section for combining items to a new one and a settings section. All of these sections are saved in a database in your project. The database is nothing else than a serialized scriptable object of type DatabaseInventory, which derives from IDatabase. To display it within an editor window, you need to access this serialized object and transfer the values to the according property fields. I will cover this in a later tutorial when we make new editor windows step by step (one with scriptable objects, another without).

Unity Editor Knowledge

In this tutorial we will, amother other things, change a script that derives from the Editorclass. Normally, when a script derives from Editor and you want to start building your project, the build will fail. This is because the class Editor is not available in built versions of the game, only in the Unity Editor. We have to place the script in a folder with the name Editor, so it doesn't get included in the built game. But why the name Editor? Unity uses so called Special folder names to tread a folder's content in a special way. See Unity Special Folders for more information.

Script Architecture/Structure

In order to extend the inventory, we need to understand how the underlying script architecture. In the project window under Assets --> Plugins --> Game Creator --> Inventory, we have a bunch of folders. Animations are in the Animations folder, editor scripts in Editor folder, actions, conditions and many more scripts in Mono and so on. We need to change the following scripts:

Filename

Folder

Usage

Derives from

Item.cs

/Mono/Items/

Defines the item object

Scriptable Object

ItemEditor.cs

/Editor/

Defines the Item Editor Window

Editor

The Item.cs defines the item object itself. This class is used when a new object of type Item is generated (like we do in the Inventory UI by clicking Create Item):

This newly generated object will be stored in the database I mentioned in a previous chapter. A method inside the script ItemEditor.cs gets executed when you click on Inventory in the sidebar of the Game Creator Preferences window, basically reading the content of the database and displaying it. In the next chapter, we will take a look at the structure of these scripts. It is better to have a certain understanding of how the scripts are structured before we continue.

Item.cs

This script contains the class Item, which contains the properties that can be set in the Inventory window and a method that allows us to create new item instances. It has properties like the name of the item, the description, if it can be sold, the price, item type and much more. There are two sections in this script. Properties and Constructor. Properties should be self-explanatory. If you open the script, we see that the Constructor (a method) section is only active in the Unity Editor. This is done with a so called define directive, here #if UNITY_EDITOR. These directives allow us to i.e. execute certain code only in the editor (like in this case), on certain platforms only (like Windows or MacOS) or when using certain Unity versions (like Unity 2020.1). Each of these define directives need an opening statement #if xxx and a closing statement #endif.

#if UNITY_EDITOR

<Your code>

#endif

ItemEditor.cs

This scripts however is much more complex. It not only contains constant variables, but static members and some methods as well. Again, we have two sections, Properties and Methods. When we open the script, we see that there are constant and static variables and a class before the Properties section. You might have heard of constant and static variables, but if not, they are not like normal variables.

Constant variables are variables with a value that, once assigned at compile-time, will never change and cannot be changed. You can only assign primitive or C# builtin types, like string and float.

Static members (i.e. variables and methods, in this case variables) are not accessible when you create a new instance of an object. They belong to the type of the object, not the instance of an object. Example:

public class Inventory
{
    public static string name = "myName"; // static string variable
    public static string GetName() {...}  // static method with string return value
}

If we create a new instance of the Inventoryclass, we won't be able to do the following:

void MyMethod()
{
    Inventory myInventory  = new Inventory();

    Debug.Log(myInventory.name); // Doesn't work!
    myInventory.GetName();       // Doesn't work!
}

We can only do this:

void MyMethod()
{
    Debug.Log(Inventory.name); // Works!
    Inventory.GetName();       // Works!
}

But back to the script. In the Properties section we have a bunch of SerializedProperty variables. A SerializedProperty is used when you want to access a value of a variable (property) of a serialized object. I will go deeper into this topic in a later tutorial. Finally, we have the Methods section of this class with all the methods. There are two particular methods to look for: OnEnable() and PaintContent()

For each item in the item database, a new object of type ItemEditor is instantiated and the method OnPreferencesWindowGUI of the same class gets called. When the objects gets instantiated, it automatically calls OnEnable(), what reads the variables of the underlying database item of type Item(which is now a serialized object) and sets the values of the ItemEditorserialized property variables to the according Item variable values (like itemName, sprite, price etc.). OnPreferencesWindowGUI does some more stuff, but also calls PaintContent(). This method paints the content of the window where the items are shown. Because we now have the serialized properties with the values of the item in the database, it is possible to simply add an EditorGUILayout.PropertyField with the serialized property as the value. Example:

// The code is simplified and shortened for better understanding

private const string PROP_PREFAB = "prefab";

void OnEnable()
{
    this.spPrefab= serializedObject.FindProperty(PROP_PREFAB);
}

public void PaintContent()
{
    EditorGUILayout.PropertyField(this.spPrefab);
}

Note: serializedObject refers to the item in the database and PROP_PREFAB to the variable. serializedObject.FindProperty(PROP_PREFAB) does nothing else than grab the value of the item object like we would with GameObject prefab = item.prefab.

Extending the inventory

Now that we have covered many things around the Game Creator inventory, we are ready to continue. For the start, let's add a string variable to the Item class (Item.cs). You can give any name you want. This is the first step to extend the inventory. Add it in the Properties section between the public GameObject prefab and public bool canBeSold variables. You can later put it anywhere in this section you like, but I do it this way for you to better understand. I include the previous and next one as well.

public GameObject prefab;

public string myVariable; // I know, not a good name...

public bool canBeSold = true;

Save it and jump over to the ItemEditor class (ItemEditor.cs). Here we do more things:

  1. Add a private constant string variable

  2. Add a public SerializedProperty variable

  3. Assign our SerializedProperty variable in OnEnable()

  4. Add a EditorGUILayout.PropertyField to PaintContent()

Let's start with the first step. Add the private constant string variable in the same position you added your string variable in the Item class:

private const string PROP_PREFAB = "prefab";
private const string PROP_MYVARIABLE = "myVariable";
private const string PROP_CANBESOLD = "canBeSold";

Attention: The value of the constant string must be the same as the name of your added variable in the Item class! In my case, my variable is called myVariable, that's why the constant string must also be myVariable.

The next thing we do is add a SerializedProperty variable to the Properties section:

private SerializedProperty spPrefab;
private SerializedProperty spMyVariable;
private SerializedProperty spCanBeSold;

Now we assign our SerializedProperty variable the value of the property value of the serialized object in the method OnEnable():

this.spPrefab = serializedObject.FindProperty(PROP_PREFAB);
this.spMyVariable = serializedObject.FindProperty(PROP_MYVARIABLE);
this.spCanBeSold = serializedObject.FindProperty(PROP_CANBESOLD);

And finally we add a property field to the method that paints the content of the window, PaintContent():

EditorGUILayout.PropertyField(this.spPrefab);

EditorGUILayout.Space();

EditorGUILayout.PropertyField(this.spMyVariable);

EditorGUILayout.Space();

EditorGUILayout.PropertyField(this.spCanBeSold);

If we switch back to Unity and let it compile, open the Game Creator Preferences window, go to the Inventory tab and create a new item. You should now see our newly added variable.

You can add as many custom entries this way as you like. You can add i.e. weapons (from the Shooter module) or anything else. Have fun making games!

Last updated