Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Copy Values To NonMono Class Or Instantiate Copy Of ScriptableObject ?

Discussion in 'Scripting' started by Reedex, May 3, 2022.

  1. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    387
    I have ScriptableObject items and for example, some random leather armor could drop with 20-40 armor. So i wonder, should i create non-ScriptableObject class and copy values every time with some copy function, or should i just Instantiate clone of that SO and tweak values?
     
    Last edited: May 3, 2022
  2. gabrielmdemelo

    gabrielmdemelo

    Joined:
    Jan 22, 2021
    Posts:
    3
    I'm not certain if I understood what you're asking, but I'll give my opinion and hope it helps anyway. I believe I would use your first option: use the ScriptableObject values to create a new non-ScriptableObject object as IIRC tweaking values of an instance of the actual ScriptableObject would be persistent in the editor even though it would not in the build.
     
  3. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,003
    The most straight-forward method would be to instantiate the SO and modify the values, but bear in mind you do need a way actually save and load these unique values, and using the JSONUtility will just leave you with a headache.

    The method I've used is to wrap the scriptable object in a plain class and have properties that act as a pass-through, checking for modifiers to the SO's values before returning them.

    This does require that your player's and other inventories all use this wrapper rather than directly use the SO.

    They mentioned Instantiating the source Scriptable Objects. Being UnityEngine.Object's you can Instaniate() them to net yourself a copy, though you also need to be sure to Destroy() when no longer being used.
     
    Reedex likes this.
  4. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    387
    Well i have Item.cs with SO Item in it. The SO Item has instantiate function "ReturnAsUnique()" where i tweak the values.
    I guess i could make an overload for ReturnAsUnique(), for loading saved values instead of random ones?
    But maybe that's not what you mean.
     
    Last edited: May 4, 2022
  5. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    387
    Well you see, i was thinking maybe that the whole new class and copy values is a bit redundant. maybe that there was better way. :d
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,003
    Not quite. I'll slap some basic code examples below:

    Say you have a basic scriptable object item:
    Code (CSharp):
    1. public class ItemObject : ScriptableObject
    2. {
    3.     [field: SerializeField]
    4.     public string ItemName { get; private set; }
    5.  
    6.     //more properties, etc, here
    7. }
    Now when you 'wrap' something, you have a class/struct that encapsulates the element in question. So something like this:
    Code (CSharp):
    1. [System.Serializable]
    2. public class ItemWrapper
    3. {
    4.     [field: SerializeField]
    5.     public ItemObject Item { get; private set; }
    6.  
    7.     public string ItemWrapperName
    8.     {
    9.         get
    10.         {
    11.             string itemName = Item.ItemName;
    12.             //check for anything modifying item name
    13.             return itemName;
    14.         }
    15.     }
    16. }
    Then you would use the item wrapper in situations where you want an item that can be modified in some way.
     
    gabrielmdemelo likes this.