Skip to content

Instantly share code, notes, and snippets.

@GeorgiyRyaposov
Created October 25, 2023 08:39
Show Gist options
  • Save GeorgiyRyaposov/3e0d89eaafe2e454cb71e1fed1fef8c3 to your computer and use it in GitHub Desktop.
Save GeorgiyRyaposov/3e0d89eaafe2e454cb71e1fed1fef8c3 to your computer and use it in GitHub Desktop.
Generate unique id for scriptable + duplicate check
using System;
using UnityEngine;
public class ScriptableObjectIdAttribute : PropertyAttribute { }
#if UNITY_EDITOR
[UnityEditor.CustomPropertyDrawer(typeof(ScriptableObjectIdAttribute))]
public class ScriptableObjectIdDrawer : UnityEditor.PropertyDrawer
{
private const string CHECKED_SCRIPTABLE_DUPLICATE_KEY = "CheckedScriptableDuplicate";
public override void OnGUI(Rect position, UnityEditor.SerializedProperty property, GUIContent label)
{
GUI.enabled = false;
if (string.IsNullOrEmpty(property.stringValue) ||
(!IsDuplicateChecked(property) && HasDuplicateId(property)))
{
if (!UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(property.serializedObject.targetObject, out var guid,
out long _))
{
property.stringValue = guid;
}
else
{
property.stringValue = Guid.NewGuid().ToString();
}
}
UnityEditor.EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true;
}
//Check other instances ID, if any has same id
//in case when scriptable was duplicated
private bool HasDuplicateId(UnityEditor.SerializedProperty property)
{
var id = property.stringValue;
var duplicates = 0;
var type = property.serializedObject.targetObject.GetType();
var otherObjects = Resources.FindObjectsOfTypeAll(type);
foreach (var obj in otherObjects)
{
if (obj is not ScriptableObject)
{
continue;
}
var serializedObj = new UnityEditor.SerializedObject(obj);
var duplicateProperty = serializedObj.FindProperty(property.name);
if (duplicateProperty == null)
{
continue;
}
if (string.Equals(duplicateProperty.stringValue, id, StringComparison.Ordinal))
{
duplicates++;
if (duplicates > 1)
{
return true;
}
}
}
SetDuplicateAsChecked(property);
return false;
}
private static bool IsDuplicateChecked(UnityEditor.SerializedProperty serializedProperty)
{
var checkedName = UnityEditor.EditorPrefs.GetString(CHECKED_SCRIPTABLE_DUPLICATE_KEY, string.Empty);
return string.Equals(serializedProperty.serializedObject.targetObject.name, checkedName, StringComparison.Ordinal);
}
private static void SetDuplicateAsChecked(UnityEditor.SerializedProperty serializedProperty)
{
UnityEditor.EditorPrefs.SetString(CHECKED_SCRIPTABLE_DUPLICATE_KEY, serializedProperty.serializedObject.targetObject.name);
}
}
#endif
private void OnValidate()
{
if (string.IsNullOrEmpty(id))
{
if (UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(this,
out var guid,
out long _))
{
id = guid;
EditorUtility.SetDirty(this);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment