Scriptableobject Unique IDs

6217020--683544--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/

6217020--683538--upload_2020-8-18_8-17-53.png

You can do it in OnValidate(). Put code to check if the I’d is null,band if so, assign a random value.

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.

ty

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.

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;

public class GuidObject : MonoBehaviour
{
    [HideInInspector] public string objID;
}

This goes in an Editor folder

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;

[CustomEditor(typeof(GuidObject))]
public class GuidObjInspector : Editor
{
    private const string OBJ_KEY_MSG = "Object Guid will be set on instance when instantiated";
    static Dictionary<string, GuidObject> storedSceneObjects;
    static Scene currentStoreObjectsScene;
    SerializedProperty objIDProp;
    bool guiEnabled;
    GuidObject guidObject;

    private void OnEnable()
    {
        guidObject = target as GuidObject;
        objIDProp = serializedObject.FindProperty("objID");

        if (storedSceneObjects == null || currentStoreObjectsScene != EditorSceneManager.GetActiveScene())
        {
            storedSceneObjects = new Dictionary<string, GuidObject>();
            currentStoreObjectsScene = EditorSceneManager.GetActiveScene();
        }

        AddThisObjectToCollection();
    }

    public override void OnInspectorGUI()
    {
        serializedObject.UpdateIfRequiredOrScript();
        DoGuidField();
        serializedObject.ApplyModifiedProperties();
    }

    private void DoGuidField()
    {
        GUI.enabled = false;
        EditorGUILayout.PropertyField(objIDProp);
        GUI.enabled = guiEnabled;

        if (!IsPrefabAsset())
        {
            if (string.IsNullOrEmpty(objIDProp.stringValue) || objIDProp.stringValue == OBJ_KEY_MSG) objIDProp.stringValue = System.Guid.NewGuid().ToString();
        }
        else if (IsPrefabAsset())
        {
            objIDProp.stringValue = "";
            EditorGUILayout.HelpBox(OBJ_KEY_MSG, MessageType.Warning);
        }
    }

    /// <summary>
    /// Returns false if the selected object isn't part of a prefab or is an instance of a prefab in a scene.
    /// </summary>
    /// <returns></returns>
    private bool IsPrefabAsset()
    {
        var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(guidObject.gameObject);
        return !(!PrefabUtility.IsPartOfPrefabAsset(guidObject.gameObject) && prefabStage == null);
    }

    private void AddThisObjectToCollection()
    {
        if (!IsPrefabAsset())
        {
            if (!storedSceneObjects.ContainsKey(objIDProp.stringValue))
            {
                storedSceneObjects.Add(objIDProp.stringValue, guidObject);
            }
            else
            {
                if (storedSceneObjects[objIDProp.stringValue] != guidObject)
                {
                    Debug.Log("Found same Guid on different scene objects, fixing...");
                    objIDProp.stringValue = System.Guid.NewGuid().ToString();
                    serializedObject.ApplyModifiedPropertiesWithoutUndo();
                    storedSceneObjects.Add(guidObject.objID, guidObject);
                }
            }
        }
    }
}