Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

[SOLVED] Proper management of collectable items

Discussion in 'Getting Started' started by Juhas0, Oct 6, 2016.

  1. Juhas0

    Juhas0

    Joined:
    Oct 4, 2016
    Posts:
    8
    Hi, I'm creating my first 3D game just to get into Unity.
    Game consists of two playable scenes. Simply you walk throught the first scene, pick some items, use them in different places and in second scene.

    My problem is that I don't know how to properly manage those collectable items. I mean, every item derives from a base class (CollectableItem), and every item when picked is added to a list (player inventory). But after picking some items and then loading other scene, my inventory seems to be empty (list has only null items).

    I know that there is something like DontDestroyObjectOnLoad, but this only works for root objects in hierarchy. My collectable items aren't root objects. They are rather groupped in hierarchy like this:

    house
    room1
    item1
    room2
    item2
    item3

    I have only one idea how to solve this problem, but I don't know if it's really proper.

    Create empty root game object and call it "Items". It will be parent for every item in game (in all scenes).
    Then create other empty root game object and call it "Inventory". Now every item that is picked by a player changes its parent to Inventory. "Inventory" game object and "Items" game object both call DontDestroyObjectOnLoad, which will prevent also all the items not to be deleted when a scene loads.

    But is it good, proper solution?
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,188
    No, I think the real problem here is that your player (the object walking through the scene and collecting items) is getting destroyed. You no doubt have another player object in the second scene that looks just like the first one... except that it doesn't have any inventory!

    So, I would suggest, delete that player object from scene two, and in scene one, call DontDestroyOnLoad on the player object. That's the thing that should travel from scene to scene.

    You will have to add something to move the player to the right starting point in scene two, but other than that, you should be all set — the inventory will stick with him, etc.
     
  3. Juhas0

    Juhas0

    Joined:
    Oct 4, 2016
    Posts:
    8
    I have that done. My player object is singleton and it persists through the scenes. His inventory is also a singleton and it persists through the scenes. But. My inventory looks like that (simplified):

    Code (CSharp):
    1. public class Inventory: IEnumerable
    2. {
    3.     List<CollectableItem> m_items = new List<CollectableItem>();
    4.         CollectableItem m_activeItem = null;
    5.  
    6.     public Inventory()
    7.     {
    8.        
    9.     }
    10.  
    11.     public CollectableItem ActiveItem
    12.     {
    13.         get { return m_activeItem; }
    14.         set
    15.         {
    16.             m_activeItem = value;
    17.             ActiveItemChanged(m_activeItem);
    18.         }
    19.     }
    20.  
    21.     public void AddItem(CollectableItem item)
    22.     {
    23.         m_items.Add(item);
    24.         if(m_items.Count == 1)
    25.             ActiveItem = m_items [0];
    26.     }
    27. }
    As you can see Inventory is not a MonoBehaviour, but it is a part of PlayerData which is MonoBehaviour and isn't deleted on new scene.
    CollectableItem is derived from MonoBehaviour and cannot call DontDestroyOnLoad because it's not a root object. So in the second scene m_items.Count has proper value, but every item in this list is set to null. So it shows that all collectable items were destroyed.
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,188
    Ah. I was assuming (and would suggest) that when you collect an object, you actually reparent it to your player object. I.e. item.transform.SetParent(transform).

    Then, because it's inside an object that's not destroyed on load, it won't get destroyed either.
     
    Juhas0 likes this.
  5. Juhas0

    Juhas0

    Joined:
    Oct 4, 2016
    Posts:
    8
    Hmm, that seems logical. Thanks, I'll do that.