# Inventory

The inventory system is built on two lists: **Items** and **Collectables**.\
**Items** is a list of `InventoryItem` objects, which extend `MonoBehaviour` and are therefore attached to GameObjects.\
**Collectables** track the quantity of each inventory item, maintaining count data independently.

<figure><img src="https://512600823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLQgz9gGwkU5HhRwKT3te%2Fuploads%2F9knka0IDDGOscLJSv1Sc%2FScreenshot%202025-04-29%20043651.png?alt=media&#x26;token=1d90642f-f550-4751-82e5-e87841187e50" alt=""><figcaption></figcaption></figure>

The **Items** list updates based on the children of the inventory GameObject. If the inventory has 10 `InventoryItem` children and one regular GameObject, the list will include only the 10 `InventoryItem` components.

## Creating an Inventory

Creating an inventory is as simple as attaching the **Inventory** component to an empty GameObject, which should be a child of the main player GameObject. This GameObject serves as both the parent for all item objects and the manager through the **Inventory** class.

{% hint style="info" %}
If you're creating a custom inventory as described in the integration section below, ensure the **Inventory** component is attached to a GameObject that is a child of the player object. Failing to do so will result in errors.
{% endhint %}

## Adding Custom Inventory Item

As explained in the summary above, the inventory automatically identifies all `InventoryItem` components that are children of the inventory GameObject. Based on this behavior, if you add a GameObject that extends `InventoryItem`, the inventory system will correctly recognize it and manage its activation (enable/disable) accordingly.

### Basic Setup

To create a custom inventory item, start by creating a new script and set its inheritance to `InventoryItem` instead of `MonoBehaviour`.

```csharp
// Required using directive
using Akila.FPSFramework;

// Inherit from the InventoryItem class
public class MyItem : InventoryItem
{
    
}
```

This script must be attached to the GameObject you want to include as a child in your inventory. For example, if you're adding a melee weapon, create the melee GameObject, attach the `MyItem` (Your Custom Script) to it, and then make it a child of the inventory GameObject. The inventory will then automatically detect it and handle switching to or from it as needed.

### Handling Pickups

To handle picking up and dropping the item, you need to create a prefab from it. In this example, we have a GameObject called **Melee** that handles melee attacks and has the `MyItem` script attached. Create a prefab from this GameObject to use it as your custom inventory item.

<figure><img src="https://512600823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLQgz9gGwkU5HhRwKT3te%2Fuploads%2FI9dm485SMIICVCl8DyVa%2FScreenshot%202025-04-29%20053836.png?alt=media&#x26;token=112aee48-273a-4edd-8b96-e0d73d133c56" alt=""><figcaption></figcaption></figure>

This prefab can then be assigned to a **Pickable** item. When the player interacts with the Pickable, it will add the item to the inventory and automatically switch to it, just like it would with any default weapon.

<figure><img src="https://512600823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLQgz9gGwkU5HhRwKT3te%2Fuploads%2FXc9jKAwXU846gfvuAj2P%2FScreenshot%202025-04-29%20054602.png?alt=media&#x26;token=ebfbf910-ea91-41e1-bf89-f863083b1db6" alt=""><figcaption></figcaption></figure>

### Handling Dropping

To drop an item, you first need a **Pickable** version of it, as shown in the code above. Once that's set up, you can begin coding the item drop functionality. Here's a simple example to demonstrate how it can be done:

```csharp
// Required using directives
using Akila.FPSFramework;
using UnityEngine;

// Inherit from the InventoryItem class
public class MyItem : InventoryItem
{
    public Pickable itemToPickup;

    // Override the Start function
    protected override void Start()
    {
        // Call the base Start method
        base.Start();

        // Assign the "replacement" field to the itemToPickup.
        // This lets the system know what item to drop.
        replacement = itemToPickup;
    }

    protected override void Update()
    {
        // Check for input
        if (Input.GetKeyDown(KeyCode.E))
        {
            // Drop the item to the ground
            Drop(true);
        }
    }
}

```

## Adding Custom Inventory Collectable

Collectables are distinct from `InventoryItems` because their primary purpose is to track the quantity of items. For example, when you add a custom health kit item and use it, you can remove one of the `HealthKitCollectables` (A custom one you made). If there are no collectables left, the health kit will be destroyed (In your health kit logic), preventing further use. This same approach is used to track the count of grenades and ammo for firearms, ensuring that their quantities are accurately managed.

You can create any of the default Collectables by opening your inventory component and clicking the "+" icon under the Collectables list.

<figure><img src="https://512600823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLQgz9gGwkU5HhRwKT3te%2Fuploads%2FeqxSwA4tHAtohvdWv8aS%2FScreenshot%202025-04-29%20063246.png?alt=media&#x26;token=c1ff0653-b1e6-45d6-a1e9-7e0218ea15fb" alt=""><figcaption></figcaption></figure>

As shown above, a new Collectable element has been added to the Collectables list, with three fields: Count, Limit, and Identifier.

* **Count** represents the current quantity of this collectable item.
* **Limit** indicates the maximum number of items this inventory can hold.
* **Identifier** is used to distinguish the collectable, determining whether it’s for HealthKits, Ammunition, or another item type.

To create an identifier, right-click anywhere in the project window and navigate to the menu: `Create > Akila > Inventory Collectable Identifier`

This will generate a scriptable object file for the inventory collectable identifier in your project, which you can then assign to the "Identifier" field.

<figure><img src="https://512600823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLQgz9gGwkU5HhRwKT3te%2Fuploads%2F2UlKdybIa4txVxF0SXCN%2FScreenshot%202025-04-29%20064139.png?alt=media&#x26;token=21833a91-e2b0-482b-b0d3-42c5745c91ad" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Don't forget to name the InventoryCollectableIdentifier you just created and set the "DisplayName" field to the appropriate name.
{% endhint %}

At this point, only the inventory recognizes the identifier. However, to make use of it, you need something that interacts with it. In code, you first need to locate the collectable in the inventory's collectables list.&#x20;

```csharp
// Required using directives
using Akila.FPSFramework;

// Inherit from the InventoryItem class
public class MyItem : InventoryItem
{
    // Assignable Identifier (Assign the one you created and assigned to the inventory)
    public InventoryCollectableIdentifier healthKitCollectableIdentifier;

    // The collectable to manage
    private InventoryCollectable healthKitCollectable;

    // Override the Start function
    protected override void Start()
    {
        // Call the base Start method
        base.Start();

        // Find the collectable by its identifier
        healthKitCollectable = inventory.collectables.Find(collectable => collectable.identifier == healthKitCollectableIdentifier);
    }

    protected override void Update()
    {
        base.Update();

        if (Input.GetKeyDown(KeyCode.T)) Heal();
    }

    public void Heal()
    {
        if (healthKitCollectable.count <= 0)
        {
            // Remove the health kit from the inventory if needed
            // Exit before executing healing logic
            return;
        }

        // Healing logic...
        Debug.Log("Healed..");

        // Decrease the count of the collectable by one
        healthKitCollectable.count--;
    }
}
```

With this code, pressing **T** calls the `Heal` function, which subtracts one from the corresponding item in the inventory's collectables list. Once the count reaches zero, the function exits early and no action is taken.

While collectables might seem unnecessary at first, they serve an important purpose. For example, they allow guns that share the same ammo type to maintain a unified "Ammo Left" count across all weapons. In the case of grenades, the grenade item is added only once, and if one already exists, its collectable count is simply increased—making it much easier to manage complex items consistently and efficiently.

### Handling Pickups

To pickup a collectable item:

1. **Set the Type**: Change the pickable's **Type** to **Collectable**.
2. **Assign the Identifier**: In the **Collectable Identifier** field, assign the identifier you created for this collectable (e.g., HealthKit, Ammo, etc.).
3. **Set the Amount**: Enter a value in the **Amount to Collect** field to define how many of this collectable should be added to the inventory's count when picked up.

<figure><img src="https://512600823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLQgz9gGwkU5HhRwKT3te%2Fuploads%2FzrICoQky9bVI0QNPcVtW%2FScreenshot%202025-04-29%20090417.png?alt=media&#x26;token=98345672-9879-4cba-9a96-14bac1eecb0c" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Make sure the same **Collectable Identifier** is also included in one of the elements within the inventory's **Collectables** list. This ensures the collected amount is properly added to the correct collectable entry.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://akila.gitbook.io/fps-framework/tutorials/character/inventory.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
