Accessing Scriptable Objects

Learn how to access Game Creator Scriptable Objects like weapons, ammo and melee weapons.

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

This version will no longer be updated and maintained.

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.

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

  • Understanding of the previous guide Inventory Custom Entries

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.

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

Shooter Module Architecture

The shooter module consists of mainly three parts:

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

Weapons

From the official documentation:

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:

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.

Melee Module Architecture

The melee module consists of mainly three parts:

  • The Weapon asset

  • The Shield asset

  • The Melee Clips asset

  • The Interaction component (undocumented, similar to the Shooter Interaction component)

Weapons

From the official documentation:

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:

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:

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.

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. My system looks like this:

You have the currently selected weapon on the left side and the currently equipped weapon on the right.

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

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.

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

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.

The method GetRifleDetails() gets called when I open the inventory or equip another weapon.

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.

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();
}

Note: rifleName, rifleImage etc. are the variables for the UI elements.

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:

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.

In order to get the stats of the selected weapon, we need to do the following:

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.

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.

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).

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.

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:

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:

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

Last updated