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. Dismiss Notice

Question How to make variables from Serializable class update in editor after a change from script ?

Discussion in 'Scripting' started by ml_unity375, Jun 22, 2023.

  1. ml_unity375

    ml_unity375

    Joined:
    Mar 6, 2023
    Posts:
    3
    Hello !
    I was trying to create a script I could use for debugging when I instanciate a lot of objects and I want to know which is which.
    I have a simple Id script, which does the logic. I would also like to have the id visible in the editor for debugging purpose, so I created an IdWrapper class, which is a Serializable class that expose the id to the editor.

    Here is my script :

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using System;
    3. using UnityEngine;
    4.  
    5. public class Id
    6. {
    7.     public int id { get; }
    8.  
    9.     private bool rememberKey = true;
    10.  
    11.     private string instanceKey;
    12.     private static Dictionary<string, int> InstanceNbs = new Dictionary<string, int>();
    13.  
    14.  
    15.  
    16.     private static readonly string defaultInstanceKey = typeof(object).FullName;
    17.  
    18.     /// <summary>
    19.     /// Create an Id count. If given a string, the count will be for all ids with the same string. If not, all ids will count toward the same type.
    20.     /// Use as follow :
    21.     /// <code>
    22.     /// Id id = new Id("MyClass");
    23.     /// Id id = new Id();
    24.     /// Debug.Log(id);
    25.     /// </code>
    26.     /// </summary>
    27.     /// <param name="key">Key Parameter is optionnal</param>
    28.     /// <param name="rememberKey">Param remember key at true will display the key in the ToString()</param>
    29.     public Id(string key = "", bool rememberKey = true)
    30.     {
    31.         this.rememberKey = rememberKey;
    32.         if (key == null || key == "")
    33.             key = defaultInstanceKey;
    34.         int nb;
    35.         if (InstanceNbs.TryGetValue(key, out nb))
    36.         {
    37.             InstanceNbs[key] = nb + 1;
    38.         }
    39.         else
    40.         {
    41.             InstanceNbs.Add(key, 1);
    42.         }
    43.         id = nb + 1;
    44.         this.instanceKey = key;
    45.     }
    46.  
    47.  
    48.     /// <summary>
    49.     /// Create an Id count. If given a type, the count will be for the type. If not, all ids will count toward the same type.
    50.     /// Use as follow :
    51.     /// <code>
    52.     /// Id id = new Id(typeof(MyClass));
    53.     /// Id id = new Id();
    54.     /// Debug.Log(id);
    55.     /// </code>
    56.     /// </summary>
    57.     /// <param name="type">Type Parameter is optionnal</param>
    58.     /// <param name="rememberKey">Param remember key at true will display the key in the ToString()</param>
    59.     public Id(System.Type type = null, bool rememberKey = true) : this((type == null) ? defaultInstanceKey : type.FullName) { }
    60.  
    61.     public Id() : this("") { }
    62.  
    63.     public override string ToString()
    64.     {
    65.         if(instanceKey == defaultInstanceKey || ! rememberKey)
    66.             return "{Id = " + id + "}";
    67.         return "{ "+instanceKey+" n° " + id + " }";
    68.     }
    69. }
    70.  
    71.  
    72. /// <summary>
    73. /// This class is used to have access to the id in the inspector
    74. /// </summary>
    75. [Serializable]
    76. public class IdWrapper
    77. {
    78.     private Id idClass;
    79.  
    80.     public int id; //View in editor
    81.  
    82.     public IdWrapper(Id p_id)
    83.     {
    84.         idClass = p_id;
    85.         id = p_id.id;
    86.     }
    87.  
    88.     public Id GetId()
    89.     {
    90.         return idClass;
    91.     }
    92.  
    93.     public override string ToString()
    94.     {
    95.         return idClass.ToString();
    96.     }
    97. }
    98.  

    But for some reason, the id var in IdWrapper stays the same in the editor, across multiple objects. (If I print them using the ToString() method it display the proper value, but when I look in the editor, all the "id" values are the same)

    Objects that are instanciated all have a script that does

    public IdWrapper Id = new IdWrapper(new Id());
    and it is the variable I look at in the editor.

    How can I have the id var display the proper value in the editor for each object ? I feel like this is a serialization problem but I don't know enough about it to be sure.

    Thanks in advance
     
  2. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,051
    You are assigning a new ID during the construction of the object (field initializers are basically part of the constructor). Unity's serialization only kicks in after construction and overwrites the ID with the one from the original object. Instantiation in Unity is basically just serializing the original object and then deserializing a new copy.

    So you want your ID to not be serialized. But due to how the inspector works, it can only show serialized fields. To show a non-serialized field in the inspector, you need to create a custom editor or a property drawer to show it.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,558
    You reeeeeeeeeallly want to avoid doing your own identifier.

    It's a HUGE source of ongoing bugs going forward.

    ScriptableObjects (can) already have a unique identifier: their
    .name
    field.

    It will be unique as long as you either a) have good discipline, or b) put all instances of one type in one folder.

    The OS will enforce uniqueness and comparing strings is essentially just as fast as an integer.

    Plus you can print out the name... hey, instant debugging, no need to go hunting for where that ID is.

    Having your on "yooneek identifier" is just a recipe for future disaster. Bug city. Even if you nail the entire logic loop PERFECTLY, there's always the future possibility of a duplicate somehow entering your system, and then you've got VERY mysterious bugs.

    Just say "No" to unique identifiers of your own. It's just not worth it.
     
    Unifikation likes this.
  4. ml_unity375

    ml_unity375

    Joined:
    Mar 6, 2023
    Posts:
    3
    Ok thank you
    Yes I guessed that it could be a source of bugs, but I have no control over the architecture of the project I am debugging, so having my own system make it easier to get the information I want. Anyway I will only use my scripts for debugging, so I don't think it will have much impact. But I will note the information just in case.


    Thank you, I think I will do that when I have some time