Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Question Scriptableobject Unique IDs

Discussion in 'Scripting' started by Quiet_Apples_Studios, Aug 18, 2020.

  1. Quiet_Apples_Studios

    Quiet_Apples_Studios

    Joined:
    Jan 27, 2020
    Posts:
    17
    upload_2020-8-18_8-21-18.png
    Hello i'd like to automatically assign a random id, when I create a scriptable object. I do not want this ID to change during run time/
     

    Attached Files:

  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,947
    You can do it in OnValidate(). Put code to check if the I'd is null,band if so, assign a random value.
     
  3. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,749
    This is fine, until you duplicate a scene object, or drag instantiate multiple of the same prefab (the prefab will already have a guid) as you will end up with the same guid in multiple objects.

    I did come up with a workaround for this which entailed using a custom inspector, but I can't find it at the moment. I'll take a another look later and see if I can dig it up.
     
    PraetorBlue likes this.
  4. Quiet_Apples_Studios

    Quiet_Apples_Studios

    Joined:
    Jan 27, 2020
    Posts:
    17
    ty
     
  5. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,749
    Sorry it took a while to get back to you, I had to strip out the relevant code from a much larger script.

    I hope this helps.

    Add this to any game object to give it a persistent guid property. Prefabs aren't allocated a guid until instantiated in a scene, and duplicated scene objects will automatically be allocated a different guid from the original.

    Tested in Unity 2019.3.14f1.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using System.Linq;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class GuidObject : MonoBehaviour
    8. {
    9.     [HideInInspector] public string objID;
    10. }
    This goes in an Editor folder
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEngine.SceneManagement;
    6. using UnityEditor.SceneManagement;
    7.  
    8. [CustomEditor(typeof(GuidObject))]
    9. public class GuidObjInspector : Editor
    10. {
    11.     private const string OBJ_KEY_MSG = "Object Guid will be set on instance when instantiated";
    12.     static Dictionary<string, GuidObject> storedSceneObjects;
    13.     static Scene currentStoreObjectsScene;
    14.     SerializedProperty objIDProp;
    15.     bool guiEnabled;
    16.     GuidObject guidObject;
    17.  
    18.     private void OnEnable()
    19.     {
    20.         guidObject = target as GuidObject;
    21.         objIDProp = serializedObject.FindProperty("objID");
    22.  
    23.         if (storedSceneObjects == null || currentStoreObjectsScene != EditorSceneManager.GetActiveScene())
    24.         {
    25.             storedSceneObjects = new Dictionary<string, GuidObject>();
    26.             currentStoreObjectsScene = EditorSceneManager.GetActiveScene();
    27.         }
    28.  
    29.         AddThisObjectToCollection();
    30.     }
    31.  
    32.     public override void OnInspectorGUI()
    33.     {
    34.         serializedObject.UpdateIfRequiredOrScript();
    35.         DoGuidField();
    36.         serializedObject.ApplyModifiedProperties();
    37.     }
    38.  
    39.     private void DoGuidField()
    40.     {
    41.         GUI.enabled = false;
    42.         EditorGUILayout.PropertyField(objIDProp);
    43.         GUI.enabled = guiEnabled;
    44.  
    45.         if (!IsPrefabAsset())
    46.         {
    47.             if (string.IsNullOrEmpty(objIDProp.stringValue) || objIDProp.stringValue == OBJ_KEY_MSG) objIDProp.stringValue = System.Guid.NewGuid().ToString();
    48.         }
    49.         else if (IsPrefabAsset())
    50.         {
    51.             objIDProp.stringValue = "";
    52.             EditorGUILayout.HelpBox(OBJ_KEY_MSG, MessageType.Warning);
    53.         }
    54.     }
    55.  
    56.     /// <summary>
    57.     /// Returns false if the selected object isn't part of a prefab or is an instance of a prefab in a scene.
    58.     /// </summary>
    59.     /// <returns></returns>
    60.     private bool IsPrefabAsset()
    61.     {
    62.         var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(guidObject.gameObject);
    63.         return !(!PrefabUtility.IsPartOfPrefabAsset(guidObject.gameObject) && prefabStage == null);
    64.     }
    65.  
    66.     private void AddThisObjectToCollection()
    67.     {
    68.         if (!IsPrefabAsset())
    69.         {
    70.             if (!storedSceneObjects.ContainsKey(objIDProp.stringValue))
    71.             {
    72.                 storedSceneObjects.Add(objIDProp.stringValue, guidObject);
    73.             }
    74.             else
    75.             {
    76.                 if (storedSceneObjects[objIDProp.stringValue] != guidObject)
    77.                 {
    78.                     Debug.Log("Found same Guid on different scene objects, fixing...");
    79.                     objIDProp.stringValue = System.Guid.NewGuid().ToString();
    80.                     serializedObject.ApplyModifiedPropertiesWithoutUndo();
    81.                     storedSceneObjects.Add(guidObject.objID, guidObject);
    82.                 }
    83.             }
    84.         }
    85.     }
    86. }
    87.  
     
    Last edited: Aug 19, 2020
    senkal_ and Quiet_Apples_Studios like this.