- Home /
Why is scene object serialized multiple times when entering play mode?
public class SerializeWatcher : MonoBehaviour, ISerializationCallbackReceiver
{
public void OnAfterDeserialize() { Debug.Log("Loaded"); }
public void OnBeforeSerialize() { Debug.Log("Saved"); }
}
I added the above script to an empty GameObject within an empty scene. I then restarted the editor (to make sure I have no unsaved changes).
When I now enter Playmode, i get the following output:
(S1) Saved
(S2) Saved
(S3) Saved
(L1) Loaded
(L2) Loaded
When I exit Playmode i get another
(L3) Loaded
S1 Callstack:
CollectSaveSceneDependencies::CollectWithRoots
CollectUsedSceneObjects
CollectAllSceneManagerAndObjectIDs
CalculateAllLevelManagersAndUsedSceneObjects
SaveScene
EditorSceneManager::SerializeSceneIntoFile
EditorSceneManager::BackupScenesFromSceneManager
PlayerLoopController::EnterPlayMode
S2 Callstack:
SerializedFile::WriteObject
PersistentManager::WriteFile
PersistentManager::WriteFile
SaveScene
EditorSceneManager::SerializeSceneIntoFile
EditorSceneManager::BackupScenesFromSceneManager
PlayerLoopController::EnterPlayMode
S3 Callstack:
SerializableManagedRefBackupGenerator::ExtractBackupFromInstance
MonoBehaviour::BackupAndDeflateManagedReferences
SerializableManagedRefsUtilities::BackupAndDeflateAll
MonoManager::BeginReloadAssembly
MonoManager::ReloadAssembly
ReloadAllUsedAssemblies
EditorSceneManager::RestoreSceneBackups
PlayerLoopController::EnterPlayMode
L1 Callstack:
SerializableManagedRefTransfer::RestoreBackup<SerializableManagedRefBackupGenerator>
SerializableManagedRefsUtilities::RestoreBackups
MonoManager::EndReloadAssembly
MonoManager::ReloadAssembly
ReloadAllUsedAssemblies
EditorSceneManager::RestoreSceneBackups
PlayerLoopController::EnterPlayMode
L2 Callstack:
MonoBehaviour::VirtualRedirectTransfer
SerializedFile::ReadObject
PersistentManager::ReadAndActivateObjectThreaded
PersistentManager::LoadFileCompletelyThreaded
LoadSceneOperation::Perform
PreloadManager::Run
L3 Callstack:
SerializedFile::ReadObject
PersistentManager::ReadAndActivateObjectThreaded
PersistentManager::LoadFileCompletelyThreaded
LoadSceneOperation::Perform
PreloadManager::Run
The only one I understand is one loading of the the object into its new PlayMode context (L2?) and the restoring of its initial state when exiting PlayMode context (L3).
And perhaps (if unity is not able to track dirty objects (i thought it did?!)) one of the Saves (S2?) to be sure not to lose unsaved changes.
My Question: What is the background of all these 6 calls?
BonusQuestion: Can I avoid any of them?
Answer by Bunny83 · Dec 31, 2018 at 09:34 AM
Lets first answer the bonus question: No you can't avoid it since This is a fundamental part of the Unity Editor.
About the individual calls: S1 and S2 most likely belong to the normal scene / project save which happens when you enter playmode. The current Scene and project state need to be saved so it can be restored to this state when leaving playmode.
S3 Looks like it's just part of the automatic reload when an assembly reload happens. When you enter playmode the whole managed environment is shutdown, saved, reloaded and restored.
L1 just belongs to S3. So it's the reload / restore after the assembly reload.
L2 is the ordinary loading of the current scene that is used in playmode.
L3 simply restores the previous scenestate.
Note that you will get much more save operations when you have selected your object in the inspector. The inspector window does only work on the serialized data of the object(s) and not the actual objects. That means you get a save each time the inspector window is refreshed (which may be every frame during playmode).
Make sure you read the page about the ISerializationCallbackReceiver carefully. They also mention thatwhen using Instantiate the object is serialized and deserialized in order to duplicate it.
Thanks for your answer. I can understand, that it works that way, but not exactly why it is neccessary.
.
(S1) Why do I have to save the current state when entering playmode? If I don't have any changes pending, everything already should be saved?! Or is it only "Saved to file" and i "Save to RA$$anonymous$$" here to have a faster (L3)?
(S2) Why do I need a second save pass if I already executed (S2)? Guess I'll just have to accept "Some internal unknown unity magic"-reasoning hiere?!
(S3/L1) If I Already have my "Regular Save/Load (S1/L2)", why don't I just get rid of all objects before Assembly Reload, if their states were saved (S1) and will be overwritten (L2) anyways?
.
Btw: I did not find any in-depth documentation on this topic (only higher level explanations like https://docs.unity3d.com/$$anonymous$$anual/script-Serialization.html and https://blogs.unity3d.com/2014/06/24/serialization-in-unity/ ). Do you know of more sources?
We can't give an exact reasoning since most of this is Unity internal and also shouldn't matter. That interface is only there to hook into the serialization system of Unity. The only point of those two callbacks is to convert custom data that can't be serialized by Unity into data / fields that Unity can serialize. $$anonymous$$eep in $$anonymous$$d that those two callbacks are executed from the load / save thread ant not from the main thread. That means you can not access most part of the Unity API.
About what is necessary and what could be avoided: Unity and the Unity editor consists of several seperate components, modules and features. The Assembly reload backup has to take care of much more than your currently active scene. There are many editor objects (editor windows, custom inspectors, managers, settings, ...) which also need to be saved. $$anonymous$$eep in $$anonymous$$d that an assembly reload also happens whenever any script need to be recompiled. The hot reload feature is seperate from the actual scene management.
Also note that the saving / restoring of the scene has nothing to do with saving the scene asset to disk. You can enter playmode with unsaved changes. Therefore Unity always creates a temporary backup of the currently loaded scene and restores it when you exit playmode. It's possible that in order to efficiently handling dependencies Unity requires a two pass save. If you look at the stacktrace of S1 and S2 you may notice that they belong to different systems.
Unless a Unity employee comes along and is allowed to share information about the internals of the serialization system you most likely won't get a better answer.
$$anonymous$$ay I ask what you actually want to do or why you care about how often Unity serializes the objects? As you can read in the documentation page of the interface you should keep the load inside those callbacks low.
Thanks again for the additional information!
I guess you're right and I'm thinking about things that are irrelevant to me. I am just currently trying to understand the details of Unity-Resource Loading (and $$anonymous$$imizing EnterPlaymode times) so I was confused about the amount of serialization.
In my project I have a lot of Dialogue-Data in every scene and it just seemed unnecessary to run through all these thousands of strings multiple times every time when entering playmode. But I guess I'll have to just keep an eye on the times and try to switch to a dynamic loading approach if it gets too time consu$$anonymous$$g.
Your answer
Follow this Question
Related Questions
Help with Binary serialization/de-serialization of List items and the WEBPLAYER 1 Answer
how to deserialize json with arbitrary string keys using JsonUtility(unity c#)? 4 Answers
Problem using a data structure created in editor mode, will not serialize? 1 Answer
EndOfStreamException : Failed to read past end of stream 1 Answer
UnityScript How To Deserialize? 1 Answer