Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How do I implement item durability and unique item ID to instantiated items?

Discussion in 'Scripting' started by ojjnartheking, Oct 7, 2021.

  1. ojjnartheking

    ojjnartheking

    Joined:
    Mar 14, 2020
    Posts:
    5
    Hello everyone! So I'm making a survival game here, I have scoured the internet for many hours, at least 6, for an answer. Haven't found any yet, so I post this question here.

    How do you implement durability to your items in-game?
    And how do you set unique item ID:s to your items which will be persistent even when you destroy the gameobject and then re-instantiate it again?

    So I have a scriptable class which is called ItemDatabase. In this class I store variables, such as itemDamage, durability, itemID, isStackable, raycastRange etc etc.

    The core problem is that I want to assign unique ID and unique item durability variables to these items. So what I did is that I created a new script where you attach the item scriptable asset to, and on method Start(), we set a unique ID with GUID (UnityEditor.GUID.Generate(), which Unity creates an ID for us). Then I want to keep this ID somehow and store it to be accessible to the same object that I can drop and equip (dropping destroys the game object if it is held in the hand and instantiates it to the world) and (picking up said object destroys it from the world and can later be equipped (instantiated) into the hand).

    So how would you implement some kind of tracking feature, that makes sure the instantiated scriptable gets the unique ID to the correct object in the world?

    NOTE: I need to instantiate each and every scriptable by code so we make sure that, if we have two or more objects of the same type, they don't share the values of the scriptable.
    For example - I have two pickaxes. Pointing directly to the Scriptable would cause them both to share durability when being used. When I instead instantiate each instance of the scriptable, they each get their own data instead of sharing the same data between eachother.

    I have heard something about memento patterns, and I will take a look into that and update this thread if that would help.

    Thanks in advance for any tips/tricks!
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    You'll need to separate your immutable and mutable data. Have the immutable data in your ScriptableObject, and your mutable data as a regular MonoBehaviour.

    Something like this:
    Code (csharp):
    1.  
    2. class ItemTemplate : ScriptableObject
    3. {
    4.    public int baseDurability;
    5.    public int baseDamage;
    6.    // etc
    7. }
    8.  
    9. class Item : MonoBehaviour
    10. {
    11.    public ItemTemplate template;
    12.  
    13.    public int durability;
    14.    public GUID guid;
    15.  
    16.    public void Load(ItemTemplate template)
    17.    {
    18.        this.template = template;
    19.  
    20.        this.durability = template.baseDurability;
    21.        this.guid = GenerateGuid();
    22.    }
    23. }
    24.  
     
    ojjnartheking likes this.
  3. ojjnartheking

    ojjnartheking

    Joined:
    Mar 14, 2020
    Posts:
    5
    Thank you for your reply! I'm going to do that approach, but how should the information be cached while an object is not "actually" destroyed? For example: an actually destroyed object will be an item that has despawned due to laying out in the world for too long, or the durability has gone down to 0, destroying the item. After that, we're allowed to demolish the cached data attached to the gameobject.

    But if it is "destroyed" via dropping and picking it up (Destroy(item.gameObject)), we still keep the data cached somehow.

    Would you recommend an itemhandler for the entire open world that keeps track of each and every single item cache and only remove data from it when items are destroyed by actually setting durability to 0 or letting them despawn? Or would this approach eventually cause slowness if there are like 10-20 people playing on the same server, each having item containers to store items, i.e chests, loot boxes, crates etc...

    This part is by far the hardest part I have come across so far.
     
  4. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    I don't have any experience working on a multiplayer open world game, but I'd assume putting an item into a storage container / inventory is no different than saving it. You'd pull out all the important bits of info that need to be saved and write that to some serialization surrogate. I don't understand what you mean with the other questions, surely when an item is destroyed you just destroy the GameObject? The template would still be safe, just the local instance and associated data would be gone.
     
  5. ojjnartheking

    ojjnartheking

    Joined:
    Mar 14, 2020
    Posts:
    5
    Hello again! So after making some more research, I came across a technique which is called "Object pooling" which could probably be a great solution for our problem. The youtuber Brackeys has a video on that topic.

    The idea is to spawn in a fixed amount of items in an objects pool and later use those objects by enabling them when you need them. The main problem I see now is unpredictability. How will you know that you've created enough items for the game that some poor player doesn't get robbed of his items because were out of ours?

    I.E - We have a fixed amount of craftable pickaxes, let's say 200. Then after that last 200th pickaxe has been crafted, we start recycling the other objects in our database (inactive objects). Would this mean that we would "steal" another players pickaxe when we craft our new 201st pickaxe?

    Predetermining all item pools to have 1 000 000 of each item would take so long to initialize... especially if our game has 300 different items, or more. Maybe we could dynamically increase the pool size if the fixed size isn't enough?
     
  6. GoliathAT

    GoliathAT

    Joined:
    Apr 12, 2014
    Posts:
    32
    Maybe you could leave the item pool empty initially and put only items you have created before and now want to deactivate into the pool.
    The pool acts as some sort of archive and will size dynamically depending on how many items are actually inactive. When you want to reuse an item, the pool will reactivate it and remove it from its list of stored items.
     
    ojjnartheking likes this.
  7. ojjnartheking

    ojjnartheking

    Joined:
    Mar 14, 2020
    Posts:
    5
    Aha, great idea! So maybe something like this:
    - Initialize Object Pool manager -> add the crafted/collected item dynamically into the pool -> Activate that item in the pool if I drop the newly created/collected item into the world and un-parent it from the player who crafted it. Sounds like a good plan! Now I just gotta figure out how to implement it in a good way. This will be a challenge