OnProcessScene sometimes gets skipped

I have a class that implements IProcessSceneWithReport and has an OnProcessScene method.
From the documentation I expect that the OnProcessScene method should be called every time I make a build, but actually it only gets called sometimes. As far as I can tell it only gets called when the scene has been changed since last time OnProcessScene was called. But I need it to be called every time I make a build!
Am I missing something? Is this a bug? Or how is the method useful when it doesn’t run for every build?

Unity does incremental builds by default. In those cases, scenes that are unchanged from the last build will not be rebuilt, in order to save time.

If that’s a problem, say if your PostProcessScene script has changed such that the scene needs to be rebuilt, you can do a clean build:
9747286--1394830--upload_2024-4-3_14-14-9.png

1 Like

Ok awesome, thanks. Didn’t know about that and it helps a lot as a workaround to force the OnProcessScene callback to run everytime.

But I’m still confused how this can be the intended behaviour - OnProcessScene is very useful precisely because it allows me to make /temporary/ changes to the scene before building that don’t persist afterwards. But since these changes don’t persist it seems obvious that the scene /does/ need to be rebuilt every time. Is this not the intended use-case for OnProcessScene? How do other people use it?

Using the ‘clean build’ option you suggested works as a worst-case fix but it’s not ideal since it takes a lot longer (since it recompiles all the scripts etc, which shouldn’t be necessary)

Is there any other way to force the OnProcessScene callback to run every time, or any other way to apply temporary changes to a scene before building? Even if I use a custom build pipeline I don’t see an obvious way to do it, because I don’t know a way to make changes to a scene and then rollback the changes after building.

One very hacky option is just to make some trivial change to the scene in OnPreprocessBuild to force the scene to rebuild, but i’m hoping that’s not the nicest solution there is, any other ideas?

Not really, no. Sorry! It seems like the only options are “clean build” and “incremental build”.

That being said, Unity recompiles all scripts anyway when you do a build, so I don’t know if an incremental build that threw away the cached scenes but kept other stuff would be much faster?

AssetPostProcessors has a nice feature where they have a GetVersion call, so if you change what version your asset post processor has, Unity knows that it has to rebuild the related assets. IProcessSceneWithReport should probably have the same kind of thing so Unity can know that the cached versions of scenes are not valid anymore.

Good point, I guess scripts get recompiled anyway, but something else is going on that takes a while, maybe 5-10x longer than a regular incremental build.

To be clear, my issue isn’t that my postprocess method has changed and so I need to make sure it gets run even when the scene hasn’t changed (although that would also be an issue). The issue is that the whole point of the postprocess callback (at least the way I am using it) is to make changes to the scene that /only affect the build/. My postprocess method makes some changes, those changes go into the build, and then after the build is done the scene is reset back to how it was originally. This works great /except/ for the fact that Unity just doesn’t call my callback unless there have been other, unrelated changes made to the scene. Whether or not the scene has been cached after a previous build is irrelevant since I still need my postprocess method to make changes to the scene before building!

I am still confused how this callback can be useful when it is set up this way, unless I’m misunderstanding its purpose.

In any case I found an ok workaround by moving around some hidden object before each build, that’s enough to force the scene to be rebuilt.

Well, the scene from the cache should have your changes already, so it shouldn’t be an issue.

When the post process script runs and changes the scene, that scene gets written to the build with those changes, and it also gets written to the cache with those changes. When you do an incremental build, the things your script did to the scene will already have happened, so it won’t have to run again, the changes from your script is already applied to the cached version, and Unity just copies the scene from the cache into the build.

Or is that not what you’re seeing happening? If you, say, spawn a red cube in PostProcessScene, do a clean build, and then do an incremental build, the red cube will still be there in the incremental build, even if PostProcessScene doesn’t run during the incremental build. It will not be there in the editor.

Ohhhh I see sorry, that makes a lot of sense.

Doesn’t quite solve the problem for me since my OnProcessScene method is also copying a bunch of files into the build directory, but I realise that’s not the standard use-case, and probably with some refactoring could make that happen in OnPostprocessBuild instead.

Thanks for the explanation!

1 Like

I agree with dd_d_dd on this, that it does not appear there is anywhere in the Unity callbacks to modify temporary scene objects out for build.

I am totally going to be stealing the modify a hidden object trick. It’s really dirty, especially cause I’ve only been able to get it to work if I also save the scene :frowning:

I don’t want to save the scene, I just want to make it so a script can make some last-minute modifications when building the scene out.

I realised the ‘hidden object trick’ was not necessary! (See my last post above) Don’t know your use case but I think just making the changes in OnProcessScene should be enough - my understanding is it only runs the first time you do a build after modifying the scene, but whatever changes happen in that function are cached somewhere and will persist in any future builds (while not appearing in the scene in the editor)

OnProcessScene is not called by default unless I perturb my scene. That is where I put my code to do the scene fixup, but, alas, I need my code to run any time any scripts change, and so I must perturb the scene to get that code to trigger.

Unless you found some trick to getting OnProcessScene to trigger even without any changes!