Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Editor Crash on AssetDatabase.SaveAssets called from OnValidate (Case 632026)

Discussion in 'Asset Database' started by andymads, Sep 9, 2014.

  1. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    I have an issue where the editor will crash every time when a script on a custom asset (ScriptableObject) calls AssetDatabase.SaveAssets from its OnValidate method when duplicating the custom asset.
     
  2. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Had the same, i guess OnValidate is triggered when you call AssetDatabase.SaveAssets which causes an infinite loop.
     
  3. LukeDJ

    LukeDJ

    Joined:
    Oct 2, 2017
    Posts:
    10
    I had this problem when calling AssetDatabase.CreateAsset from OnValidate. My fix was to put the asset-creation code in a coroutine, flipping a boolean in OnValidate to prevent the coroutine from being called infinitely, and using yield return null before creating the asset to allow enough time for the boolean to be updated.
    Here's a basic demo that uses an inspector-assigned mesh and boolean that, when selected, allows a clone of the mesh to be saved as an asset file:
    Code (CSharp):
    1. using System.Collections;
    2. using System.IO;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. public class MeshAssetSaver : MonoBehaviour
    7. {
    8.     [Space(5)]
    9.     [SerializeField] private Mesh mesh;
    10.     [Space(5)]
    11.     [SerializeField] private bool saveMeshAsset;
    12.  
    13.     private void OnValidate()
    14.     {
    15.         if (saveMeshAsset)
    16.         {
    17.             saveMeshAsset = false;
    18.  
    19.             StartCoroutine(SaveMeshAsset(mesh));
    20.         }
    21.     }
    22.  
    23.     private IEnumerator SaveMeshAsset(Mesh mesh)
    24.     {
    25.         string path = EditorUtility.SaveFilePanelInProject("Save Mesh Asset", mesh.name, "asset", "", Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)));
    26.         if (string.IsNullOrEmpty(path))
    27.         {
    28.             yield break;
    29.         }
    30.  
    31.         yield return null;
    32.         AssetDatabase.CreateAsset(Instantiate(mesh), path);
    33.     }
    34. }