Search Unity

List of ScriptableObjects not being saved in Prefab Mode

Discussion in 'Prefabs' started by KMacro, Jan 7, 2019.

  1. KMacro

    KMacro

    Joined:
    Jan 7, 2019
    Posts:
    9
    Here is the code I am using.

    Code (CSharp):
    1. public override void OnInspectorGUI()
    2. {
    3.     MyScript myScript = target as MyScript;
    4.     SerializedObject myScriptObj = new SerializedObject(myScript);
    5.     SerializedProperty myList = myScriptObj.FindProperty("MyList");
    6.     EditorGUILayout.PropertyField(myList, true);
    7.  
    8.     EditorGUI.BeginChangeCheck();
    9.     choiceIndex = EditorGUILayout.Popup(choiceIndex, Enum.GetNames(typeof(myScriptableObjectTypes)));
    10.     if (EditorGUI.EndChangeCheck())
    11.     {
    12.         switch(choiceIndex)
    13.         {
    14.             case 0:
    15.                myScript.myList.Add(CreateInstance<ScriptableObject1>());
    16.                 break;
    17.             case 1:
    18.                 myScript.myList.Add(CreateInstance<ScriptableObject2>());
    19.                 break;
    20.             case 2:
    21.                myScript.myList.Add(CreateInstance<ScriptableObject3>());
    22.                 break;
    23.         }
    24.         EditorUtility.SetDirty(target);
    25.         EditorSceneManager.MarkSceneDirty(myScript.gameObject.scene);
    26.     }
    27.  
    28.     myScriptObj.ApplyModifiedProperties();
    29. }
    This works fine when modifying an object in a regular scene. I add things to my list, save the scene and reload it, and the list is as I set it. However, if I make changes in prefab mode, save the changes, back out of prefab mode and reenter, the list is the correct size, but all objects in it are null.

    Am I doing something wrong or is this a bug with Prefab mode?
     
  2. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    573
    runevision likes this.
  3. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,502
    Correct.

    When you create asset type objects (such as ScriptableObjects) and don't save them as Assets, they are normally stored in the scene where they are being referenced. So I expect they appeared as overrides in your scene when you do this in a regular scene, since they live in the scene and can't be referenced from the Prefab Asset itself. When you do this in Prefab mode, the objects will be discarded when Prefab Mode is closed. I suggest you save your ScriptableObjects as assets using the AssetDatabase API, whether as their own assets or adding it to an existing asset such as the Prefab.
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    3,682
    Adding assets to prefabs is a pretty compelling use case, especially now that we have nesting. If I'm making animations for a button prefab, I'd love to have the animation clips and controller as sub-assets of the button prefab rather than somewhere else, to keep the project hierarchy tidy.

    It also makes perfect sense to have eg. materials used by only one enemy be a part of that prefab, and so on.

    Unity supports this pretty well, except on the interface side. Any thoughts on exposing a view of sub-assets of a prefab in the prefab view?
     
  5. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,502
    Thoughts? I'm in favor.

    But it's not something we've had luck getting prioritized to go further with.
     
    SugoiDev and Flavelius like this.
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    3,682
    That's a pretty good way to do it!

    For the prefab view in particular, a much less invasive approach would be to add a section to the hierarchy that just flatly listed all of the sub-assets of the prefab, with the ability to drag-and-drop to and from the asset folder, and right-click/create asset.

    ... that could actually be done user-side, by creating an EditorWindow and docking it. I could even grab some code off my colleague's ScriptableObject Window. Then, again, I do already have too many side-projects going.
     
    Last edited: Jan 8, 2019
  7. KMacro

    KMacro

    Joined:
    Jan 7, 2019
    Posts:
    9
  8. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    3,682
    @runevision, did you ever look into how to handle subobjects with missing scripts when doing that?

    If I add a ScriptableObject as a subasset of some other object, and then delete the script that defines that SO, there seems to be no way to delete it other than to open the .asset file in a text editor. I can't delete it from the project view, and I can't delete it from scripts, as I can't get a reference to it (it loads as null).

    Not the correct forum for this, but since we were on the subject already...
     
  9. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,502
    I don't think we looked at that, no. Since this is already an issue today, you could file a bug report on this if you haven't already.
     
  10. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    3,682
    Will do.

    By the way, is it a bug that you can't delete sub-assets from the project view at all? If you click one and hit "delete", nothing happens:

    Bug.gif

    It's been that way so long that I've assumed it's intended - right click shows both Rename and Deleted as grayed out. It's really inconvenient, but I'm assuming that it's a feature request rather than a bug report?
     
  11. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    407
    @Baste
    I think it was simply just not implemented. You can delete subassets using
    DestroyImmedate(someObj, true)
     
  12. KMacro

    KMacro

    Joined:
    Jan 7, 2019
    Posts:
    9
    I'm running into a different issue with the same code. I have added the following line after line 23 in the code I originally posted.

    Code (CSharp):
    1. AssetDatabase.AddObjectToAsset([the Scriptable Object I create], PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath);
    This works fine, but if I enter Prefab Mode, add one element to the list, back out of Prefab Mode, reenter Prefab Mode, and add another element to the list, both elements become null at the start of the next OnInspectorGUI.

    Any thoughts?
     
  13. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    573
  14. KMacro

    KMacro

    Joined:
    Jan 7, 2019
    Posts:
    9
    I still experience the problem, even when I mark the prefab scene dirty.

    The only work around I have found is to use AssetDatabase.SaveAssets() immediately after I add or remove an object from the prefab asset. Behaviorally, this works okay, but causes the currently selected object to lose focus in the editor whenever I modify the list, which is kind of a pain. If I hold off on saving my list until the user backs out of the prefab scene, I still experience the issues with null ScriptableObjects I explained above.
     
  15. KMacro

    KMacro

    Joined:
    Jan 7, 2019
    Posts:
    9
    Found another quirk. Regardless of whether I use AssetDatabase.SaveAssets() after adding a ScriptableObject, if I make any change to any of the other components attached to my prefab, all entries in my list become null.