0
\$\begingroup\$

I'm currently working on an Inventory/Equipment System and so far have been using a Singleton Pattern to instantiate my Inventory and Equipment classes. I was wondering if i attach this Script to multiple gameObjects, whether they each have a seperate instance or whether they share it? This would be important for the Equipment classes as each GameObject should obviously have different Items equipped. My current Singleton pattern looks like this:

public static Inventory Instance { get { return instance; } }

void Awake()
{
    if(instance != null && instance != this)
    {
        Destroy(this.gameObject);
        Debug.LogWarning("More than one instance of Inventory found!");
        return;
    }
    instance = this;
}
\$\endgroup\$
0
\$\begingroup\$

If you need different instances of the inventory for different game objects, but want to ensure that you always have one single inventory per game object, then the singleton pattern is not the right pattern here.

I would simply use a read-only field or property for the inventory

public class MyGameObject : GameObject
{
    public Inventory Inventory { get; } = new Inventory();
}

Like this, each game object having an inventory creates his own single inventory being distinct from inventories of other game objects.

Note: Read only means that you cannot delete or replace the inventory object; however, you can still add objects to or remove objects from the inventory.


Probably some kinds of objects have an inventory, others do not. E.g. a treasure box has an inventory, while a stone doesn't. Therefore I would create an interface for the better distinction

public IInventoryHolder
{
    Inventory Inventory { get; }
}

public class MyGameObject : GameObject, IInventoryHolder
{
    public Inventory Inventory { get; } = new Inventory();
}

Then instead of having statements like

if (gameObject is TreasureBox || gameObject is Player || gameObject  is whatever...) {
    gameObject.Inventory.Add(item);
}

You can write

if (gameObject is IInventoryHolder inventoryHolder) {
    inventoryHolder.Add(item);
}
\$\endgroup\$
  • \$\begingroup\$ I think this is the solution to my problem. I guess my question in the end was basically whether a Script attached to a Gameobject would share the same variable if its also attached to another Gameobject, but since i want to have differentiated Inventories however still make sure each Gameobject the script is attached to only has one Inventory-object, the singleton pattern i used was wrong, thanks! \$\endgroup\$ – Veineless Apr 29 '18 at 16:30
1
\$\begingroup\$

I was wondering if i attach this Script to multiple gameObjects, whether they each have a seperate instance or whether they share it?

Well, let's walk through the code to see what happens.

Let's say we have this script attached to Object1 and Object2, and Object1 happens to load first....

Object1

// Object1's inventory script's Awake() gets called.
void Awake()
{
    // Nothing has yet set instance, so instance == null.
    if(instance != null && instance != this)
    {
        // The if test fails, and we skip over the part inside the braces.
    }
    // instance is now set to point to Object1's inventory script
    instance = this;
}

So, at the end of Awake, instance is pointing to Object1's attached inventory script.

Now Object2 loads...

Object2

// Object2's inventory script's Awake() gets called
void Awake()
{
    // Now instance is not null, it's pointing at Object1's inventory script.
    // But "this" is Object2's inventory script, so instance != this.
    if(instance != null && instance != this)
    {
        // We enter the if, Destroy Object2, log a warning, and exit early.
        Destroy(this.gameObject);
        Debug.LogWarning("More than one instance of Inventory found!");
        return;
    }
    // Since we exited early, nothing else happens.
}

So, the result is that you have only one instance of the inventory script in existence, because all the other objects that had the inventory script attached destroy themselves on load.

If this is not your desired behaviour, then this might not be the right pattern for your application. Unfortunately, we don't have enough context about what you're trying to do to know for sure what you might need instead. Feel free to ask a new question describing your application & how the feature should work if you need some tips on how to achieve it.

\$\endgroup\$
  • \$\begingroup\$ As Olivier described, my goal was to have multiple gameobjects with the same Inventory Script attached, however still make sure each gameobject has only one distinct inventory object to work with, so that i can potentially expand my game to having multiple characters being played, that both have distinct inventories, or for example a chest which would have an inventory aswell, but obviously has different items inside than my main character would have. \$\endgroup\$ – Veineless Apr 29 '18 at 16:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.