Categories
Advanced Tutorials

Using the Inventory Package

Preface

In this tutorial we will learn how to use the Inventory package provided by Crayta to help us easily set up a system to manage a player’s inventory.

Crayta has an inbuilt Asset Library which provides easy access to packages provided by the Crayta team or Crayta users.

A Crayta Package, is a collection of templates, scripts, widgets etc that can be easily shared between Crayta projects to enhance the functionality of your game.

The Crayta team provides and maintains a collection of packages (Game, Shop, Inventory etc) that can help you easily put in place the basic functionality for a game or learn by studying how they work.

Installing the Inventory Package

Using the Community Tab of the Asset Library window in the editor we can easily install the inventory package to any game by selecting it from the packages list and selecting install.

Crayta will download and install the package to your game alongside any dependencies required. You can now see what the package has imported to your project by selecting and expanding it in the Packages section of the library window:

Structure of the Inventory Package

Let’s take a look at the contents of the package that are now available to be used in our game. A Crayta package can contain any kind of assets that can be authored in the editor (meshes, effects, scripts, templates etc.). In this case the Inventory package imported two templates, a widget and a number of scripts.

Templates

  • User Inventory, is a simple template that holds the main inventoryScript component and an example of setting a default item.
  • Player Inventory View, is a template containing the Widget/UI logic for the inventory.

Those templates provide a basic layout on how to structure your inventory logic, you can use them as they are by dragging them straight onto the User and Player template accordingly or attaching the required scripts and widgets yourself to the User/Player entity.

Widget

  • inventoryViewWidget, this is a Crayta widget asset (a file containing HTML/CSS/Javascript) which is responsible for rendering the inventory interface on screen. This widget has to be attached to the Player template to work.

The default layout renders a configurable number of slots at the bottom of the screen, each slot can be empty or hold an item. Using HTML/CSS you can easily add your own styling to the interface.

The inventory system is highly flexible and can even store weapons.

Scripts

  • inventoryScript, this is the heart of the inventory system, this script is responsible for initialising and managing all inventory items. To use this script attach it to the User template.
  • inventoryDefaultScript, this is an optional script used to set the default items in inventory slots that are available when the game starts. You can attach this on any entity (the inventoryScript can be configured where to look for default items) or add it to the User template.
  • inventoryViewScript, this script is responsible for communicating all inventory logic to the inventory widget for rendering. It also handles equipping/unequipping items and passing through inputs / button presses to the currently equipped item. It should be attached together with the widget to the Player template.
  • inventoryItemSpecScript, is used to define an item which can be picked up by the Player and added to the inventory. It should be attached to a Template.
  • pickupSpawnerScript, this is an optional script used to handle spawning and respawning pickups of items that can be picked by the Player and added to the inventory. It can be either attached to a Template to use that template as pickup or to any entity and be configured to use a template as the pickup item.

Most of the methods in the inventory scripts have detailed comments explaining how they work and what they do, making it easy to understand and extend their behavior.

How to setup the inventory

Let’s examine now how we can start using those scripts to setup a basic inventory easily and quickly in our game.

Putting the scripts in place

After installing the package we should start by adding the base inventory scripts and widgets in place. We can do that easily by:

  1. Dragging and dropping the User Inventory template from the inventory package to our User template.
  2. Dragging and dropping the Player Inventory View template from the inventory package to our Player template.

Those two templates will add script folders with the inventory scripts to our User/Player templates.

Make sure you drag the templates into the correct user and player templates.

Running the game by pressing the preview button will render the inventory automatically.

You can see the empty inventory UI at the bottom of the screen.

Adding items to the inventory

There are some steps to making an item become collectable: first we have to turn the item into a template, and then we need to add the appropriate scripts to it.

Choose the Meshes tab from the Library and then pick a suitable mesh, in my case I have picked the Donut-Jumbo mesh and dragged it into my World and then made sure it’s highlighted in the World hierarchy.

Select Template > Create New Template. Give your new template a name (we’ve called ours ‘Donut’).

Create a new template of the collectable item.

At the top of the world tree you need to click the drop-down to change the view from World to your template:

Click the dropdown to select your template.

You now need to add the inventoryItemSpecScript to your template:

  • Select Entity > Add > Script > inventoryItemSpecScript

The inventoryItemSpecScript makes it easy to make any template in our game ready to be added to the inventory. We can give it a friendly name (such as ‘Donut’) for the player to see, choose whether it becomes a stacked item, and what grip the player’s character should use when they carry it.

We can also add an icon to represent the item when it’s displayed on the UI. To do this, simply find the Mesh in the Library and drag it onto the Icon Asset slot. You should see the name of the mesh appear to let you know it worked.

Make sure that you have configured your inventory item fully and added an icon.

This script adds the required properties to any template so that it can now be added to the player’s inventory.

To actually appear in the Player’s inventory, we have two options – let’s explore both.

Option 1: Start with the item in the inventory

Adding the User Inventory template to our User template created a new script folder called Defaults

Add an inventoryDefaultScript component to this folder, and set the template to the one for your item (i.e. Donut). You should now start with the item already in the player’s inventory. Here you can also configure the quantity of this item the User will start with by playing with the count property.

Running the game now you will see an item being automatically added to the inventory. The Player carries it on its assigned grip position. If no grip position is selected, the item will attach to the right hand by default.

Option 2: Add pickup items to the game

Having the Player carrying all the items from the start of the game might make it too easy and not so fun. Let’s learn how to easily add pickup spawnable items to the game world.

If you want to stop carrying donuts (or whatever mesh you picked.) when you start the game, remember to remove this from the inventoryDefautlScript for your User template.

Open the template you created for your inventory item and then add the pickupSpawnerScript to your custom item template. Now this script comes with a large number of properties to customize it to your liking:

  1. For the moment let’s decrease the min/max respawnTime property to 5 seconds, which affects how often the item will respawn after it is picked by the Player.
  2. Also be sure to enable the showOnInit property which will make the item available from the start of the game.

Return to the World Tree and add a few instances of this template to the World. Now if you go and preview the game you will find yourself able to start picking up those items with the Interact key.

You can also enable the useOnCollision property on the pickupSpawnerScript to have the Player pick up any item they collide with automatically.

Configuring the inventory

You will notice that you can pick up several items and the number of items on that slot will increase. That is happening thanks to the canStack property on the inventoryItemSpecScript.

Go ahead and disable canStack and run the game again. You will see that as soon as you pick up this item, it will be added to the next free slot of the inventory. Trying to pick up more items will fail since your inventory is full.

I wish that I could carry more donuts!

To have more slots available go ahead on the User template and on the inventoryScript increase the maxSize property.

Now I can hold a lot more donuts.

Using inventory items

We now have an inventory full of useful items, so how do we use them? The inventory package has by default input configured to use the following controls:

  1. Extra Action 2/Extra Action 3 to switch the active inventory slot to the previous/next slot. This is an easy way to cycle through your inventory items in game.
  2. Hotbar 1,2,3,4 etc to change the active inventory slot by its index

Advanced inventory features

Extending the default styling

To start extending the default styling provided by the inventory package, you have to edit the HTML/CSS code found in the inventoryViewWidget widget.

If you select the UI Widgets from the Library and then open the inventoryViewWidget from there.

Let’s change the styling of the selected item. To do that locate the .item-selected class in the widget CSS, select the class name and all the code included the braces and replace it with the following code:

	.item-selected {
		opacity: 1;
		background-color: #ff751a;
		text-shadow: 0 0.1rem rgba(0,0,0,.3);
		box-shadow: 0px 0px 0px 0.1rem #fff inset;
		border-radius: 50px;
	}

This will increase the border-radius in the CSS mark-up making the item slot round.

Let’s make all item slots match this style by updating the .item and .item-empty classes accordingly, repeat the process by finding these classes and replacing them with the following:

	.item {
		margin-right: 0.25rem;
		display: block;
		background-color: #f3cda5;
		text-align: center;
		width: 6rem;
		border-radius: 0.25rem;
		height: 6rem;
		color: white;
		opacity: 0.8;
		z-index: 1;
		background-size: cover;
		border-radius: 50px;
	}
	.item-empty {
		background-color: #8888;
		border-radius: 50px;
	}

And also update the .item-hotkey class to center the slot index; see that we are changing just the text-align from left to center:

	.item-hotkey {
		width: 5rem;
		display: block;
		text-align: center;
		padding-top: 0.2rem;
		font-size: 0.75rem;
	}
Changing the layout of the CSS can give the UI I new and different feel.

Saving/loading items

You can install a package available in the Crayta store, called Auto-save that can help you persist a Player’s inventory items between sessions or when changing worlds.

Installing the package will add two scripts in your project, the autoSaveScript and the inventorySaveScript.

To enable this functionality all you have to do is add those two scripts to your User template. To make it a little neater, right-click on the User and select Create Child > Script Folder > New Script Folder and then rename this to AutoSave.

There is only a single property that needs us to configure it is called interval. This sets the gameplay time after it elapses the inventory will automatically save in the background.

I’m going to reduce this to 10 seconds for testing purposes, when the Player starts a new session or moves to a new world, his inventory will be automatically filled with the items he had in place.

Removing inventory items

Many inventory items in games can be used limited times or just once before they are consumed. The inventory package doesn’t provide an automatic way to handle that, though it provides a method that you can easily use from any script to add item removal logic.

Firstly, we will need to select the Scripts tab from the Library. Find the inventoryScript and then open it so we can inspect it:

function InventoryScript:RemoveCurrent(removeCount)
	return self:RemoveFromItem(self.inventory[self.hotbarInfo.hotbarIndex], removeCount)
end

Let’s create a new script by selecting Create New Script and then call it consumeItemScript and populate it with the following code:

local ConsumeItemScript = {}

function ConsumeItemScript:OnButtonReleased(btnName)
    if btnName == "interact" then
        self.inventoryScript = self:GetEntity():GetUser().inventoryScript
        self.inventoryScript:RemoveCurrent(1)
    end
end

return ConsumeItemScript

Now attach this script to your Player template, as with the inventory script we should create a new script folder and call it consumeItemScript and then place the above script on it.

Preview the game, make sure the item is in your inventory and then try pressing the interact action button.

The active item will be used once and then it will be removed from the inventory.

Accessing the inventory items

All items the inventory holds, together with info regarding their quantity and the slot index they occupy, are stored in the self.inventory table in the inventoryScript.

Here is sample code on how to access that table from another User/Player script and print the item names and amounts in the console:

local ConsumeItemScript = {}

function ConsumeItemScript:OnButtonReleased(btnName)
    if btnName == "interact" then
        self.inventoryScript = self:GetEntity():GetUser().inventoryScript
        for index, inventoryItem in ipairs(self.inventoryScript.inventory) do     
        	if inventoryItem.template ~= nil then
            	Printf('You have consumed 1 {1} of {2} {1}\'s.', inventoryItem.template:GetName(), inventoryItem.count)
        	end
    	end
    	self.inventoryScript:RemoveCurrent(1)
    end
end

return ConsumeItemScript

Conclusion

In this tutorial you have seen how to install the inventory package , how you can use it to pick up and stack the items you’re carrying, how to stylise the inventory UI, and how to remove items from your inventory.

This could be used in many ways in the games you built, maybe you have a game that requires the player to gather and sell items at a shop, or you need to collect a certain number of items for a door to unlock. as always, we cannot wait to see what you build in Crayta!