LoadAssetAtPath doesn't seem to work for ScriptableObject asset in AssetPostProcessor

Hello there !

I have been trying to implement a very simple AssetPostProcessor to force the collider type on Tile assets during import, depending on the path of the asset. We are starting to have hundreds of tiles and something like this would really help.

When I reimport my tile asset, the asset path is logged successfully but LoadAssetAtPath always returns null. I’ve been looking for solutions and alternatives for a while now but I really can’t figure out what’s is wrong in this code. Any tips ?

Edit : I’m on Unity 2019.4.10f1, this script is in an Editor assembly. I also tried LoadMainAssetAtPath and tried to log values in the assetImporter (name, userData are all empty…)

Thanks a lot

class TileAssetImporter : AssetPostprocessor
    {
        void OnPreprocessAsset()
        {
            if (assetPath.Contains("Collider_"))
            {
                Tile tile = AssetDatabase.LoadAssetAtPath<Tile>(assetPath);

                Debug.Log(assetPath);

                if (null != tile)
                {
                    if (assetPath.Contains("None"))
                    {
                        tile.colliderType = Tile.ColliderType.None;
                    }
                    else if (assetPath.Contains("Sprite"))
                    {
                        tile.colliderType = Tile.ColliderType.Sprite;
                    }
                    else
                    {
                        tile.colliderType = Tile.ColliderType.Grid;
                    }

                    EditorUtility.SetDirty(tile);
                    AssetDatabase.SaveAssets();
                }
                else
                {
                    Debug.LogError("Could not load Tile asset");
                }
            }
        }
    }

Update for those who my be facing a similar issue : I wasn’t able to make it work using OnPreProcessAsset. I suspect a regression because it used to work in Unity 2018.3 (I’m now using 2019.4.10f1)

However, I can load my ScriptableObject (here, a Tile) during post process and do what I want that way. I don’t consider this to be the best solution, it looks quite unelegant and I still don’t understand what was going on with the previous code, but hey, it works now. The dirty flags are here so that I won’t enter an infinite loop, since AssetDatabase.SaveAssets() will end up reimporting and this code will therefore be called again. Source code :

    class TileAssetImporter : AssetPostprocessor
    {
        static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
        {
            bool hasDirtyAssets = false;

            foreach (string path in importedAssets)
            {
                if (path.Contains("Collider_"))
                {
                    Tile tile = AssetDatabase.LoadAssetAtPath<Tile>(path);

                    bool isDirty = false;

                    if (null != tile)
                    {
                        if (path.Contains("None"))
                        {
                            if(tile.colliderType != Tile.ColliderType.None)
                            {
                                tile.colliderType = Tile.ColliderType.None;
                                isDirty = true;
                            }
                        }
                        else if (path.Contains("Sprite"))
                        {
                            if (tile.colliderType != Tile.ColliderType.Sprite)
                            {
                                tile.colliderType = Tile.ColliderType.Sprite;
                                isDirty = true;
                            }
                        }
                        else
                        {
                            if (tile.colliderType != Tile.ColliderType.Grid)
                            {
                                tile.colliderType = Tile.ColliderType.Grid;
                                isDirty = true;
                            }
                        }

                        if(true == isDirty)
                        {
                            hasDirtyAssets = true;
                            Debug.Log("TILE IMPORTER - changed tile collider to " + tile.colliderType.ToString() + " for " + path);
                            EditorUtility.SetDirty(tile);
                        }
                    }
                }
            }

            if(true == hasDirtyAssets)
            {
                AssetDatabase.SaveAssets();
            }
        }
    }
}