# Accessing Scriptable Objects

{% hint style="danger" %}
The documentation has moved to: <https://mitschmr-studios.io/documentation/api-guides/accessscriptableobjects.html>

This version will no longer be updated and maintained.&#x20;
{% endhint %}

In this tutorial, I want to show you how you can access scriptable objects like weapons and ammo by using HookPlayer and Inventory i.e. to compare the stats of a weapon. &#x20;

### Prerequisites

* Install Unity
* Install IDE (I use Visual Studio 2019)
* Import Game Creator
* Import and enable the Inventory module
* Import and enable the Shooter module
* Import and enable the Melee module
* Understanding of the previous guide [Access Player Using HookPlayer](https://docs.mitschmr-studios.io/gc-api-guides/access-player-using-hookplayer)
* Understanding of the previous guide [Inventory Custom Entries](https://docs.mitschmr-studios.io/gc-api-guides/inventory-custom-entries)

{% hint style="info" %}
Note: You don't need to buy a module if you don't use it. If you only use melee weapons, then you don't need the shooter module and vice versa. I have both on the list for the tutorial only.&#x20;
{% endhint %}

{% hint style="info" %}
Note 2: I assume that when you equip a weapon (melee or shooter, doesn't matter) in the inventory, you also draw the weapon. If you are not using the inventory module, I have prepared a case without it. [Case #2](#case-2-accessing-weapon-stats-without-inventory)
{% endhint %}

### Shooter Module Architecture

The shooter module consists of mainly three parts:&#x20;

* The [**Weapon**](https://docs.gamecreator.io/shooter/shooter/weapons) asset
* The [**Ammo**](https://docs.gamecreator.io/shooter/shooter/ammunition) asset
* The [**Interaction**](https://docs.gamecreator.io/shooter/shooter/interaction) component

To learn more about each part, I recommend to read the official documentation. I only briefly cover the basics of each part.&#x20;

#### Weapons

From the official documentation:&#x20;

> **Weapons** are scriptable objects that allow to configure how a weapon looks like, how to hold it, as well as link it to a particular **Ammo** object.

#### Ammo

From the official documentation:&#x20;

> **Ammunition** (from now on **Ammo**) are the other objects used by the **Shooter** module that allow you to create any kind of weapon. **Weapon** objects allow you to define how the **Character** behaves using a certain gun, but **Ammo** allows to define what happens when shooting it, charging shots, how the aiming is done, etc...

#### Interaction

So that a character or the player knows which weapon he is holding right now, he needs to have a component attached. **PlayerShooter** for the player and **CharacterShooter** for a character.&#x20;

![](https://3625548948-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6E9D__lMnHqqxqKxIn%2F-MD9lI03I8ysVepzNMVn%2F-MD9lUPRUITbh_8dmlUG%2Fimage.png?alt=media\&token=6753cfc8-728a-4238-8e21-665f48a6285d)

### Melee Module Architecture

The melee module consists of mainly three parts:&#x20;

* The [**Weapon**](https://docs.gamecreator.io/melee/melee/weapons) asset
* The [**Shield**](https://docs.gamecreator.io/melee/melee/shields) asset
* The [**Melee Clips**](https://docs.gamecreator.io/melee/melee/melee-clips) asset
* The **Interaction** component (undocumented, similar to the Shooter Interaction component)

#### Weapons

From the official documentation:&#x20;

> The Weapon asset represents the definition of a specific weapon of your game. From a simple *Steel Sword* to a *Fire spellbound Battle Axe*.

#### Shields

From the official documentation:&#x20;

> **Shield** assets complement **Weapon** assets and provide a way to block incoming attacks, as well as determine how much pressure the wielder can withstand.

#### Melee Clips

From the official documentation:&#x20;

> **Melee Clips** are the essential part of the **Melee** module. You can think them as animation clips in steroids, where you can not only define what animation will be played, but also what effects this animation has, when these happen and how this affects the character and enemies behavior.

#### Interaction

So that a character or the player knows which weapon he is holding right now, he needs to have a component attached. This is the **CharacterMelee** component for both a character and the player.&#x20;

![](https://3625548948-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6E9D__lMnHqqxqKxIn%2F-MD9ytmJgv2SIt2wnX9u%2F-MD9yzh3nhIne5XdZBqo%2Fimage.png?alt=media\&token=72a42326-69fa-4f2c-8fd4-dd2511352144)

### Case #1 - Comparing Weapon Stats in the Inventory

Comparing the statistics of different weapons is a normal use case in any shooter game. For this example I use the weapon comparing feature in the game I develop, [Defnite](https://docs.mitschmr-studios.io/games/defnite). My system looks like this:&#x20;

![](https://3625548948-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6E9D__lMnHqqxqKxIn%2F-MD9zIkQ7GaaN7mWIUHa%2F-MDA-52tnhnYNSOEUmnm%2FInventory.png?alt=media\&token=bd91a6fc-53f8-4d4e-b9e6-91a294147a53)

You have the currently selected weapon on the left side and the currently equipped weapon on the right.&#x20;

#### Setup

In order to compare the stats of the weapons, I needed to extend my inventory with a field for my weapon (type `Weapon`) and add a weapon asset to it. To learn how to extend the inventory, follow this guide: [Inventory Custom Entries](https://docs.mitschmr-studios.io/gc-api-guides/inventory-custom-entries)&#x20;

![](https://3625548948-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6E9D__lMnHqqxqKxIn%2F-MDAAv68XYOKujlwXM76%2F-MDABWGbe_CoLRJXRySN%2Fimage.png?alt=media\&token=af4c66a2-fca4-411e-9679-a1148eb3bb7c)

#### Inventory UI - Equipped Weapon

In my inventory UI prefab, I made two sections (one for the selected and one for the equipped weapon) and added several text gameobjects to hold the values of each weapon stat I want to compare. The next thing I did was to add a script to the top gameobject that contains all the UI elements for my equipped weapon. The script has public references to each comparable element.&#x20;

![](https://3625548948-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6E9D__lMnHqqxqKxIn%2F-MDA1eRYOjvYNg509b-V%2F-MDA1s1c8IxAvlxtskPz%2Fimage.png?alt=media\&token=ca5a2c26-9932-4b1c-87c9-5af56e1a9692)

In order to get access to these statistics, I need to first get a reference of my equipped weapon item:&#x20;

```csharp
public void GetRifleDetails()
{
    Item equippedRifle = InventoryManager.Instance.GetEquip(HookPlayer.Instance.gameObject, 0);
    SetRifleDetails(equippedRifle);
}
```

The method `GetEquip()` accesses the `PlayerEquipment` component of the specified gameobject and searches for equipped items of a specified type. In my case, it reads the inventory of my player and searches for equipped items of type **Rifles**.&#x20;

The method `GetRifleDetails()` gets called when I open the inventory or equip another weapon.&#x20;

Now that we have a reference to our currently equipped weapon item, how do we get access to the weapon item stats? Well, we access the newly added `weapon` field and now we can get every stat we want.&#x20;

```csharp
private void SetRifleDetails(Item target)
{
    rifleName.text = target.itemName.GetText();
    rifleImage.sprite = target.sprite;
    rifleRecoil.text = "Recoil: " + target.weapon.defaultAmmo.recoil.ToString();
    rifleFireRate.text = "Fire Rate: " + target.weapon.defaultAmmo.fireRate.ToString();
    rifleClipSize.text = "Clip Size: " + target.weapon.defaultAmmo.clipSize.ToString();
    rifleFocusTime.text = "Focus Time: " + target.weapon.defaultAmmo.crosshairFocusTime.ToString();
    rifleAccuracy.text = "Accuracy: " + target.weapon.defaultAmmo.maxSpread.ToString();
    rifleVelocity.text = "Velocity: " + target.weapon.defaultAmmo.projectileVelocity.ToString();
}
```

{% hint style="info" %}
Note: `rifleName`, `rifleImage` etc. are the variables for the UI elements.&#x20;
{% endhint %}

#### Inventory UI - Selected Weapon

To get the stats of a selected weapon, we need to add a script to the inventory item prefab (i.e. ItemRPG). Because the script is not aware of the inventory UI (seperate prefabs, not in the scene) we can't reference the UI elements easily. What we need to do is find them by using `GameObject.Find()`. This approach is slower than the above one, but it doesn't have a big impact on performance because we aren't using it all the time. Let's have a look at some examples:&#x20;

```csharp
void OnEnable()
{
    itemName = GameObject.Find("WeaponSelectedName").GetComponent<TextMeshProUGUI>();
    itemImage = GameObject.Find("WeaponSelectedImage").GetComponent<Image>();
    <...>
}
```

`GameObject.Find()` searches the hierarchy for a gameobject with a certain name. In the end this is the same as using `public TextMeshProUGUI itemName;` and dragging the gameobject with the TextMesh component on it.&#x20;

In order to get the stats of the selected weapon, we need to do the following:&#x20;

```csharp
public void GetItemDetails()
{
    weaponItem = gameObject.GetComponent<ItemUI>().itemObject;
    SetRifleDetails(weaponItem);
}

private void SetRifleDetails(Item target)
{
    itemName.text = target.itemName.GetText();
    itemImage.sprite = target.sprite;
    weaponRecoil.text = "Recoil: " + target.weapon.defaultAmmo.recoil.ToString();
    weaponFireRate.text = "Fire Rate: " + target.weapon.defaultAmmo.fireRate.ToString();
    weaponClipSize.text = "Clip Size: " + target.weapon.defaultAmmo.clipSize.ToString();
    weaponFocusTime.text = "Focus Time: " + target.weapon.defaultAmmo.crosshairFocusTime.ToString();
    weaponAccuracy.text = "Accuracy: " + target.weapon.defaultAmmo.maxSpread.ToString();
    weaponVelocity.text = "Velocity: " + target.weapon.defaultAmmo.projectileVelocity.ToString();
}
```

The method `GetItemDetails()` needs to be called whenever I click on an item.&#x20;

![](https://3625548948-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6E9D__lMnHqqxqKxIn%2F-MDAIGZRH_IkOap9VCQJ%2F-MDAIaExN_YYJI0AlOU9%2Fimage.png?alt=media\&token=049a845e-ef04-4935-964f-6c517963828c)

The item prefab has a component on it called `ItemUI` which holds a reference to the item in the database. By using `.itemObject`, we get a reference to this item and can now access the weapon values. Finally the stats are written to the UI elements.&#x20;

### Case #2 - Accessing Weapon Stats Without Inventory

In order to get the weapon stats without using the inventory module, we need to access the `PlayerShooter` component (for the player) or the `CharacterShooter` (for characters).&#x20;

```csharp
void GetWeaponDetails()
{
    Weapon playerWeapon = HookPlayer.Instance.GetComponent<PlayerShooter>();
    Debug.Log(playerWeapon.weaponName);
    Debug.Log(playerWeapon.defaultAmmo.recoil.ToString());
}
```

### Case #3 - Accessing a Melee Weapon

To get the stats of a melee weapon, you can do the same approaches I showed above for the shooter module. The only things you need to change are the types of the objects and the stats you are looking for.&#x20;

#### Inventory UI

Add a field of type `MeleeWeapon` to your item in the item catalogue the same way you add custom entries to it. Drag and drop a melee weapon asset on it to get a reference to this weapon. You can then simply access the melee weapon:&#x20;

```csharp
meleeWeaponName.text = target.meleeWeapon.weaponName.GetText();
meleeWeaponImage.sprite = target.sprite;
meleeWeaponName.text = "Name: " + target.meleeWeapon.weaponName.GetText();
```

#### Interaction Component

Get a reference to the `CharacterMelee` component and you are good to go:&#x20;

```csharp
void GetWeaponDetails()
{
    CharacterMelee playerMelee = HookPlayer.Instance.GetComponent<CharacterMelee>();
    Debug.Log(playerMelee.currentWeapon.weaponName.GetText());
}
```
