Search Unity

Prefabs saving over and over ?

Discussion in 'Prefabs' started by zh4r0naX, Mar 17, 2019.

  1. zh4r0naX

    zh4r0naX

    Joined:
    Oct 30, 2016
    Posts:
    71
    Hello, ive got a question. Ive got some Problems with my Prefabs, those Prefabs arent big but they keep saving over and over again.

    upload_2019-3-17_23-19-18.png

    This loading bar comes up after saving the project for like 6 times. Same happens when clicking on collab. This is annoying and takes up to a minute, right now ive got just 7 rooms, dont want to imagine how much time i will lose when i got like 100 different rooms.

    Also if i just add a random new script and hit collab it everytime shows that prefabs got changed, while i didnt do.

    how can i find the root of this problem and solve it ?

    When i duplicate a prefab the same message pops up. Its annoying and time consuming. I dont want it to get out of hand when my rooms increase.

    This is what a room is made of

    upload_2019-3-17_23-27-52.png

    Any ideas ?
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    You can check the root cause through the profiler. Turn on deep profiling and profile editor, and you should get a usable stack trace showing what's causing it.

    Then, send a bug report, because this is obviously not an acceptable performance regression.
     
  3. zh4r0naX

    zh4r0naX

    Joined:
    Oct 30, 2016
    Posts:
    71
    Thank you for your response. Sadly profiler isnt helping me out, could still be everything.

    Ive got one big spike. Prefabs.SavePrefab is using it up. But why are they saved that often ?

    upload_2019-3-18_19-11-55.png
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    It seems like there's something really bad going on with the new prefab system both getting dirtied way too often, and taking way too long to save.
    Or the system's just exposing some preexisting issues where things gets dirtied when they shouldn't.

    Either way, if you can reproduce this consistently, send a bug report and then @runevision or somebody else working on this can take a look.
     
  5. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    What we've seen in the bug reports we've gotten is:
    • Usage of the SVG package which has an issue that sets Prefab Assets dirty too often. A bug has been assigned to the team maintaining that package.
    • User scripts that mark Prefabs dirty too often.
    As always, if you're seeing issues you think are bugs in Unity, file a bug report. Write the case number here if you want to make sure it ends up on our table.
     
  6. prisonerjohn

    prisonerjohn

    Joined:
    Jul 31, 2013
    Posts:
    28
    I had a similar issue a few weeks ago and realized that there's an Auto-Save toggle in the Prefab editor that is enabled by default. I think what it does is save prefabs every time they change automatically, and that caused my editor to keep checking and updating prefabs non-stop.

    Capture-PrefabSave.PNG

    If that is your issue, also note that this is a per-install setting (not per project), so you'll need to change it on all your machines.
     
    warpfx and marwan-smg like this.
  7. zh4r0naX

    zh4r0naX

    Joined:
    Oct 30, 2016
    Posts:
    71
    Thank you for all those answers. Like @runevision mentioned it was a asset which marked prefabs as dirty all the time.. this is now fixed after i contacted the asset developer.

    Thank you all.
     
    runevision likes this.
  8. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
  9. marwan-smg

    marwan-smg

    Joined:
    Feb 3, 2020
    Posts:
    1
  10. rawboy8128

    rawboy8128

    Joined:
    Jan 27, 2020
    Posts:
    1
    I have the same problem.

    I found that one of my scripts still changes an asset when the unity call OnValidate. So I'll fix it.
     
  11. warpfx

    warpfx

    Joined:
    Feb 10, 2020
    Posts:
    14
    Necromancing the post because after the whole day of thinking Why The Heck Unity is saving the prefab on disk on every mark of dirtyness (RecordPrefabInstancePropertyModifications/SetDirty/MarkSceneDirty) the solution way so easy. Just to unmark the "Auto Save" toggle. I'm creating a plugin for 3D editing models just like Crocotile3D and must somehow prevent such a save overload.

    BTW. Is it normal that Unity saves the Prefab's file on every SetDirty() call?
     
  12. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Depends on what you mean by "normal"! Not in any other context, but in prefab mode, yes.

    I'm pretty sure that the prefab mode's AutoSave toggle just makes it check in every editor update if the preview scene is dirty, and if so writes to file.

    It's convenient in the specific case where you're working on UGUI, and want to see the changes reflected immediately to a game view on the secondary monitor. Otherwise it's painful as hell.
     
  13. warpfx

    warpfx

    Joined:
    Feb 10, 2020
    Posts:
    14
    Thanks for reply! I understand that Auto Save may be convenient in most cases.

    However, my Prefab contains editable Mesh and I need to inform editor that changes have been made. Thus way when saving the scene, e.g. via CTRL+S Prefab should be saved on the disk. The problem is that
    EditorUtility.SetDirty(obj)
    or
    Undo.*AnyMethod
    will immediately save the Prefab to the file. If Mesh is huge, then it saves e.g., 5 MB Prefab file on every move of the point. I tried to use:

    PrefabUtility.RecordPrefabInstancePropertyModifications(obj)

    new SerializedObject(obj).ApplyModifiedProperties();

    EditorSceneManager.MarkSceneDirty(obj.gameObject.scene);

    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());


    But none of them sets object as Dirty, so saving the scene won't save the Prefab. I could add "On Scene Save" handler to mark all modified prefabs as Dirty, but that would be a hack I would like to avoid.

    Ideal solution is to just uncheck "Auto Save". Is it possible to uncheck it programatically? Or inform editor that Prefab has changed without saving it on the disk, but forcing the save when user saves the scene?
     
  14. warpfx

    warpfx

    Joined:
    Feb 10, 2020
    Posts:
    14
    I've done some research and after several hours I found that several Unity packages uses reflection in order to access some internal classes. It is exactly what I needed in order to access AutoSave boolean from
    UnityEditor.SceneManagement.StageNavigationManager
    's instance.

    Here is the code required for component editor to enable/disable auto-save when entering into Prefab Edit mode. Auto-save toggle will be normally editable by the user. It is just set once when entering Prefab Edit mode.

    Note that auto-save toggle is not per object, but global. If you disable it in one prefab, the value will stay as it is if you enter another prefab.

    Code (CSharp):
    1. [CustomEditor(typeof(FooComponent))]
    2. public class FooEditor : UnityEditor.Editor
    3. {
    4.    void OnEnable()
    5.    {
    6.        PrefabStage.prefabStageOpened += OnPrefabStageOpened;
    7.    }
    8.  
    9.    void OnDisable()
    10.    {
    11.        PrefabStage.prefabStageOpened -= OnPrefabStageOpened;
    12.    }
    13.  
    14.    void OnPrefabStageOpened(PrefabStage stage)
    15.    {
    16.        var initialPrefabsAutoSaveValue = <INITIAL VALUE OF AUTOSAVE BOOLEAN TO BE SET WHEN OPENING THE PREFAB USING THIS EDITOR>;
    17.  
    18.        Type stageNavigatorManagerType = typeof(UnityEditor.SceneManagement.PrefabStage).Assembly.GetType("UnityEditor.SceneManagement.StageNavigationManager");
    19.  
    20.        PropertyInfo instanceProperty = stageNavigatorManagerType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
    21.        if (instanceProperty != null)
    22.        {
    23.            var instanceValue = instanceProperty.GetValue(instanceProperty);
    24.  
    25.            if (instanceValue != null)
    26.            {
    27.                PropertyInfo autoSaveProperty = instanceProperty.PropertyType.GetProperty("autoSave", BindingFlags.Instance | BindingFlags.NonPublic);
    28.                if (autoSaveProperty != null)
    29.                    autoSaveProperty.SetValue(instanceValue, initialPrefabsAutoSaveValue);
    30.            }
    31.        }
    32.    }
    33. }
    34.  
    Works like a charm!
     
    Last edited: Dec 17, 2022
    hafu985 likes this.