OnValidate can be troublesome when dealing with assets created through duplication, and you’ll need to handle dirtying and resaving the asset if it generates a new ID, which can be a little tricky because some API is unavailable there.
The best way I know to detect when an asset has been created is to use the first parameter in AssetPostprocessor.OnPostProcessAllAssets. It also detects when an object has been created by means like ctrl+D. It has a parameter with deleted asset paths that you might be able to use to remove ids from your database. If you only want to intercept creation through the menu, you can use something like this:
using UnityEngine;
using UnityEditor;
using UnityEditor.ProjectWindowCallback;
public static class SomeSOMenuItems
{
[MenuItem("Assets/Create/SomeSO", false, 0)]
static void CreateNewAsset()
{
var newObject = ScriptableObject.CreateInstance<SomeSO>();
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(
newObject.GetInstanceID(),
ScriptableObject.CreateInstance<DoCreateSomeSOAsset>(),
"Default SomeSO Name.asset",
AssetPreview.GetMiniThumbnail(newObject),
null);
}
}
class DoCreateSomeSOAsset : EndNameEditAction
{
public override void Action(int instanceId, string path, string resFile)
{
var obj = EditorUtility.InstanceIDToObject(instanceId) as SomeSO;
// Do something to obj here.
path = AssetDatabase.GenerateUniqueAssetPath(path);
AssetDatabase.CreateAsset(obj, path);
ProjectWindowUtil.FrameObjectInProjectWindow(instanceId);
}
public override void Cancelled(int instanceId, string path, string resFile) => Selection.activeObject = null;
}
I’d suggest using a proper GUID stored in a string instead of a number. A plain number, specially if it’s obtained by increments, will have high chances of collision when using version control or when multiple persons are collaborating. That is, unless you don’t need the IDs to survive through multiple sessions, then you can just use GetInstanceID().
I feel like I must warn you: Serializing references to assets through custom unique IDs can still get you into lots of trouble. Like, if two persons create an asset in the same path, now you have a new layer of issues to deal with when merging. Or If an asset gets created or deleted outside of the Editor (i.e. in Version Control) there could easily be a mess. If there’s a bug in Unity’s code or yours that prevents an ID from being generated, you can have a silent ID inconsistency. Even when everything is properly caught in the Editor, you need to deal with missing IDs and database inconsistencies manually.
I think Kurt’s suggestion of using name+pathName as IDs can be a good compromise to solve many of those problems, because then your IDs are visible to the users, and you can count on everything, even the file explorer, for dealing with some of the potential issues, like duplication.