FPS Advice for Item Management

Hello,

Working with C#, I’ve been looking into plausible methods for item management, and more specifically, item data storage. My requirements are:

  • Five item classes (Weapon, Collectable, Food etc.)
  • Of these five classes, there are 5-10 different item types. (Machine gun, pistol, sniper rifle etc). No difference in script, just different variables in the inspector.
  • Of these items, each individual item has its properties edited at runtime. (Weapon.fRateOfFire += 1)
  • Every single object needs to be able to be picked up/dropped, and stored in the player inventory.

While I’m not looking for one outright answer, any and all advice you could give to improve my method, or suggest appropriate alternatives, would be highly valuable.

My method

  • Item Manager: Stores the functions that allow picking up/dropping, and structures that the player can use to store variable data for instances of items.
  • Player_Generic: On a per-player basis, this script attaches to the player prefab, and deals with controls, interactions, and player data storage, including the player inventory. Every time the player picks up an object, its data is copied from its script and placed into this structure, to be stored in a list.
  • (Example) Item_Weapon: The class for each item type. This only contains public variables, and is attached to each item prefab.
  • Item_Weapon_Pistol(In the pistol prefab): In the inspector, I can set default values for these items. These will be spawned into the game world with their default properties, and during run-time, these variables can be edited.

While, in theory, this will work fine, it does seem like somewhere, what I’m doing is unnecessary. For example, I’m storing individual item properties in two places, depending on where it is. I.e. Both in the instance of the object, or as a structure inside the Player_Generic script. Ideally, I would just reference a global list of items. However, I have no idea how to save that, especially with varying structure types.

Which leads me to my next problem, how can I store multiple structs of varying (and sometimes identical) types in an inventory? Similar to minecraft, you could have two identical items, except one has high durability, while one has low. I know I need to make a primitive GUID system, but its only necessary for the inventory, as, outside it, items are separated by scripts.

To pick up items, I’ve got a working ray cast from player mouse, that returns the game object hit if it has the tag “Item”. I then check that item for each of the scripts:

  1. Attempt to get the first script type using getcomponent. (working)
  2. If it is not null, get the data of that type (working) and put it into a struct. (not attempted yet, so far I can debug.log the data that I obtain)
  3. Delete the instance and return (working)
  4. If it is null, repeat with next script type, and see if the item contains that script.

The trouble I’ve had with structuring Unity scripts is that it differs quite dramatically with the language I’m learning primarily (C++). While I’ve been adjusting, I’m always worried that the methods that I’ve got for each system is completely inefficient, I just cant think of a better way.

However, from what I’ve read, making a global list of all items, and then simply moving the reference to the player inventory, seems to be the best option, I just need an example of that (or a base) to work with.

Cheers for reading, and thanks for the help!

To solve the duplicate properties issues, you can ‘delegate’ the properties to a data class. The item object and Player_Generic will then have a reference to the data rather than dealing with copies.

To make sure thoses data are editable inside Unity, just make a Serializable class. Something like:

public interface Item_Data
{
}

[System.Serializable]
public class Item_WeaponData : Item_Data
{
    public float yourVariable;

    // ...
}

public class Item_Weapon : MonoBehaviour
{
    public Item_WeaponData data;

    // ...
}

public class Player_Generic : MonoBehaviour
{
    public List<Item_Data> itemsDataList;

    // ...
}