Search Unity

How to obtain hidden ScriptableObject assets with missing scripts?

Discussion in 'Editor & General Support' started by oscarAbraham, Jan 16, 2021.

  1. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    I have some scriptable objects added as subassets with
    AssetDatabase.AddObjectToAsset
    . They have the HideInHierarchy HideFlag, so they can't be seen in the project window, to avoid clutter. The thing is that, if the script behind the asset is missing for some reason, I can't select them to repair them.

    I've tried to get those objects with
    AssetDatabase.LoadAllAssetsAtPath
    , so that I can reassign their script with code, or at least change their HideFlags so they become selectable in the project window and I can manually reassign their script, but all I get is null objects. I can't seem to find a way to access them, other than manually modifying the asset in a text editor. I really need to implement a way to repair them in the Unity Editor.

    Does anybody know a way to access those objects? I'd really appreciate it, it's kind of breaking my head. Thank you very much for your time. I hope you have a nice day.
     
  2. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    So, I got tired of worrying about this and I made a solution that's a little rough. It modifies the text file directly, which feels kind of rash, but it really seems like the best that I can do. I'd still love a solution through the Editor API, though.

    This methods go in the ScriptableObject that's the main object of the asset. I used ContextMenu instead of MenuItem to avoid cluttering the asset menu:


    Code (CSharp):
    1. #if UNITY_EDITOR
    2.         [ContextMenu("Show Subassets", true)]
    3.         bool ValidateShowSubAssets()
    4.         {
    5.             return AssetDatabase.Contains(this) && AssetDatabase.IsOpenForEdit(this);
    6.         }
    7.  
    8.         [ContextMenu("Show Subassets")]
    9.         void ShowSubAssets()
    10.         {
    11.             //TODO add a confirmation dialog.
    12.             var path = AssetDatabase.GetAssetPath(this);
    13.             AssetDatabase.ReleaseCachedFileHandles();
    14.  
    15.             if (!File.Exists(path))
    16.             {
    17.                 Debug.LogError("Cannot find asset file", this);
    18.                 return;
    19.             }
    20.  
    21.             string[] lines = File.ReadAllLines(path);
    22.  
    23.             if (lines.Length < 1 || !lines[0].Contains("YAML"))
    24.             {
    25.                 Debug.LogError("Cannot parse asset file. Make sure Asset Serialation Mode is set to text.", this);
    26.                 return;
    27.             }
    28.  
    29.             for (int i = 0; i < lines.Length; i++)
    30.             {
    31.                 lines[i] = lines[i].Replace("m_ObjectHideFlags: 1", "m_ObjectHideFlags: 0");
    32.             }
    33.  
    34.             File.WriteAllLines(path, lines);
    35.             AssetDatabase.Refresh();
    36.         }
    37. #endif
    It needs the System.IO and the UnityEditor namespaces. If you set the hideFlags in the OnEnable callback of your subassets like I do, only the objects with a missing script will be shown in the project window, which can be nice. Otherwise, you can replicate that effect by getting all the objects with
    AssetDatabase.LoadAllAssetsAtPath
    , and set
    hideFlags = HideFlags.HideInHierarchy
    for objects that are subassets and have the correct type.
     
    Last edited: Jan 17, 2021