How I Manage Long Compile Times in Unity

How I Manage Long Compile Times in Unity

Unity's script compilation can be painfully slow in large projects, and it can seriously disrupt workflow and developer momentum. In my case, with a fairly large project, full domain reloads were taking 30–45 seconds on average. Interestingly, compilation for changes in certain assemblies was relatively quick (3–5 seconds), but other parts of the domain reload process were dragging things down.



⚠️ Note: This post focuses specifically on script compile times in the Unity Editor, including domain reload and reflection delays that occur after code changes. It does not cover strategies for runtime build optimization (e.g., IL2CPP or build pipeline tweaks), nor does it address the time it takes to enter play mode.

Here are a few strategies I use to keep compile and iteration times manageable:

☠️ InitializeOnLoad Can Be Death by a Thousand Cuts

While InitializeOnLoad callbacks and similar can be lightweight individually, they can add up quickly — especially in large projects that include a lot of third-party assets. Each little callback might only cost a fraction of a second, but when you're dealing with dozens or hundreds of them, it becomes noticeable.



Tips:

  • Audit and reduce your use of InitializeOnLoad and similar editor callbacks.

  • Be selective about third-party assets and packages — many bring hidden callbacks with them.

  • Unused built-in packages like Cinemachine, Timeline, etc., may also include InitializeOnLoad usage. Remove what you don’t use.

📦 Use Addressables

Unity’s Addressables system can help both at runtime and in the editor:

  • It decouples asset dependencies, which can reduce domain reload overhead.

  • It gives you more control over when and how assets are loaded.

The setup has a bit of a learning curve, but it pays off — especially in large projects with many assets.

🔥 Hot Reloading

There’s a great third-party tool that enables code hot reloading without full recompilation:

🔗 Hot Reload – Unity Asset Store

While I haven’t fully adopted it in production yet — it uses some kind of code injection which makes me a bit wary — it could be a game-changer for iteration speed during prototyping or smaller projects.

📐 Assembly Definitions (AsmDefs)

Assembly Definitions are essential for managing compile time in Unity:

  • Keep a clean and logical dependency graph.

  • Wrap third-party code in AsmDefs if they aren’t already.

  • Modularize your project. For example:

    • My Sys assembly is atomic — it has no dependencies.

    • My InfluenceMap assembly only references Sys and Core.

Also, disabling automatic compilation on code changes can improve iteration flow:

  • You can continue inspecting the editor while making changes.

  • You can rerun the game before recompiling, which speeds up debugging and testing.

📊 Track Compile Times with This Tool

Here’s a great open-source tool that helps visualize Unity's compilation process:

🔗 Compilation Visualizer – GitHub

It gives you:

  • A breakdown of what’s being recompiled.

  • How long each phase takes.

  • A baseline to monitor when your editor is bogging down and may need a restart.

It’s an essential tool in my toolbox for keeping an eye on performance drift over time.







🧠 Unity Profiler

Don’t forget the Unity Profiler. It can actually give you timing data for script compilation and domain reload.

Use it to:

  • Spot unexpected spikes or delays.

  • Validate whether optimizations are actually helping.

  • Identify bottlenecks you might not expect (like asset processing during domain reload).





🧹 Keep the Project Tidy

Having unused code and assets lying around doesn’t just clutter your project — it can slow things down:

  • While it doesn’t drastically affect raw compile times,

  • It does impact the Reload Domain phase — Unity still has to scan and register everything.


This tool helped me clean up abandoned assets:

🔗 Unity Dependencies Hunter – GitHub

Unused code can also increase compile time unnecessarily. Even though script compilation times were fine for me, trimming dead code might save you more time depending on your project structure.




Final Thoughts

Unity still has a long way to go in terms of making large projects feel fast and responsive during iteration. But with the right habits and tooling, it’s absolutely possible to reclaim your development flow.

These strategies helped me reduce waiting time and keep the iteration loop snappy. I hope they help you too!

I pulled this from my X-Men GDD.  We used visuals to help us communicate attacks and moves. We defined these early even though we used an agile process.  Many moves were changed significantly over the course development process but it was important to communicate with our team members and external partners what we were building and how each character felt and differed. The artist put these together after some cross-disciplinary high-level design meetings.  Because we could build these so fast, we created a vocabulary of moves and decided which ones went to prototype.  In the end we had over 100 moves for 12 playable characters.  We followed a similar approach to enemy and boss design.

Fungus Interactive Narrative Middleware for Unity

I've been using Fungus for a few days.  So far I have really enjoyed using it and it has sped up my production.    Written by Chris Gregan It's an open source Interactive Story Telling library for Unity.  It has a simple visual scripting language, very similar my own Helios Scripting Language and provides a graphical and data-driven way to author interactive narratives. 

What I am trying to do, is create stock dialog for various prefabbed enemy types.  Enemies will say certain things depending on the status of the battle.  I have many prefabbed enemies: BlightDragon, UndeadKnight, ShadyRogue, etc.  Naturally, I would add a Fungus.FlowChart to each of these prefabs.  

There is a particular challenge that limits the viability of the scripting Language in that you cannot make prefabs from GameObjects that have a Flowchart child.  What happens is that the FlowChart object will loose all of its references to UI Text Game Objects that the flow charts point to.  For Unity, this is how prefabs have to work -- they cannot contain references to objects instantiated in the scene. 

I am not sure if this is a limitation of Fungus with Unity 4+ UI's only as I am not looking at the other features of Fungus.  When I was onboarding to the tech, it felt like Fungus was specific to its own UI framework so it was nice to see Fungus support the new Unity UI so elegantly. Hopefully, the Fungus team can fix this design limitation.  

For now, I worked around the issue by duplicating the Write Command with my own CustomWrite Command that resolves the UI.Text object target.  Oh yeah, Fungus is extensible making it even more useful. 

 

You can learn more about Fungus for  Unity here: http://fungusgames.com

Prefab Evolution

So it turns out that I needed a more complex solution for nested prefabs. My game has a menu based upgrade system where the player must upgrade a building with facilities.  I modelled each building facility with a GameObject Prefab.  I have different stock buildings that have pre-arranged collections of facilities.  Buildings are themselves game object prefabs.  

I went with Prefab Evolution.  it is pretty slick, although It seems to need to reindex (Check Prefab Dependencies) things every once in a while.  I've read some comments that this could be slow for larger projects.  So far I haven't noticed any big hiccups.  For 25$ -- worth. 

 

You can get Prefab Evolution for Unity here: https://www.assetstore.unity3d.com/en/#!/content/17557

 

Nested Prefabs In Unity

Unity has a great system for prefabbing game objects.  The only problem is that if you nest a prefab inside another prefab, unity will inline the contents of the child prefab.  Unity has nested prefabs in their version road map, but the ETA is unknown and hasn't been slotted since version 5.4.  I have some game objects that I need to reuse. Each instance needs to be slightly different and has some custom parameters. I also need to embed these game objects into other game objects.  Here is a simple, but nice work around that works for my needs.

http://framebunker.com/blog/poor-mans-nested-prefabs/

 

There are also several 3rd party solutions available on the asset store, but am not sure how well those work however.  

Large Scenes in Unity 5.3

Overview

I have been playing around in Unity for a couple of weeks now and I am attempting to do a game with lots of entities that are prearranged in a very large map.  It is a minimal exploration art game.  I was looking for an approach to manage a substantial amount of entities in a large scene.  This is both a performance issue and an operational one.  I assume it would be hard to manage a large scene with thousands of entities.  Not only would editor load times stifle the creative process, but traversing through a large level hard to manage.  I would also assume that multiple designers working the single scene would be challenging.  After doing some digging I found some nice tutorials on creating open world games (GTA, Skyrim, etc),  but they do not address the large scene problem.  After some digging, I noticed some methods of the SceneManager class of the Unity framework.  The specific function in question are the additive and scene merging functionality. There did not seem to be much documentation or examples of the use of the SceneManager's additive load functionality.  

My game would have hundreds of these unique sections each containing dozens of entities.   The solution that is presented below allows for a clean way to organize a large world with many entities.  It would allow for many developers to author in this large world and minimize performance issues of having many objects loaded simultaneously.

This is a simple tutorial, and the first article I have written in a long time. Hopefully some of you will find it useful.  As well, I would love any feedback on my approach.

 

 

Approach

Here is the approach:  There are many scenes, each containing a small and specific section of the of large world.  A master scene contains a set of triggers that load/unload each section (I call them subscenes) based on the player location.   Each section are oriented in its own local space at (0,0).  When loaded, we transform all the game objects by a transform that maps the locally oriented objects of the section into the coordinate space of the large world. 

We will be using the additive loading functionality of the SceneManager.  The following lines of code will load and unload the level content.


      SceneManager.LoadScene( aSceneName, LoadSceneMode.Additive );

      SceneManager.UnloadScene( aSceneName );

 

Master Scene - A master scene contains a set of triggers that load/unload each section based on the player location.  It also contains the Player,  Game Controllers and other subsystems of your game.  Below is a depiction of what our Master Scene might looks like.  It only has four nodes right now but the idea is that we would have hundreds.  Also the example imply some sort of fantasy theme.  This example was picked to help articulate the approach.  Each green circle is a unique SubsceneTrigger game object that corresponds to a specific subscene.  The subscene is loaded when the player enters the collision region and unloaded when the player exists the region.   Each SubsceneTrigger entity is responsible for loading/unload its associated scene. 

 

SubsceneManager - There is not much here.  We justneed a place to keep track of the Subscene-To-World-Space transform.  This position is set to the transform of current SubsceneTrigger that the player is in proximity to.   We assume that our Subscenes will be axis aligned with the world transform.   Eventually we may add more functionality to the SubsceneManager. SubsceneManager could be made Signleton or added to you're GameController.  See the improvements section for additional details on what we may use the SubsceneManager for.

 

SubsceneTrigger - A SubsceneTrigger will be responsible for updating the SubsceneManagers Subscene-To-World-Space transform.  When the player enters a SubsceneTrigger, the Subscene-To-World-Space transform is updated.  We only use position in our example because we assume our Subscenes transformation contains no scalar or rotational aspects.  The SubsceneTrigger will also also be responsible for the loading/unloading of each scene.  Here is how the SubsceneTrigger game object looks like in the Inspector.  We require a Collider trigger actuate the loading/unloading of the subscene.

 

The code is quite simple.  We listen for the collision trigger events from the associated Collider2D component.  Feel free to use the collision2D shapes of your choice.   Note, there is a bug that will crash Unity if the UnloadScene is called from OnTriggerExit.  We differ it using a coroutine.  We could also move it to the Update as well.  Here is the thread that discusses the specific Unity bug.

 

 

Subscene - Now that we can load and unload subscenes, lets take a look at the subscene.  To bypass the necessity of transforming each of the entities of the subscene, we can simply add all entities of the subscene to a root game object.  This root node will reference the SceneManager and apply the Subscene-To-World transform.  The script that accomplishes this is theSubSceneRoot script. The code is quite simple.  We just need to set offset the root gameobject's (SubsceneRoot), by the Subscene-To-World transform. 

Note that all game objects the subscene are children of the SubsceneRoot.  We author our sub scenes around the origin (0,0).  Each subscene must be structured this way.  Alternatively, each entity could also each contain the SubsceneRoot script but that would be much more of a performance burden.

 

Conclusion

That's about it.  It is a pretty simple technique that can make large worlds viable from a performance perspective and much easier to operationalize. This technique would work well for large open world games.  I have added some notes about improving the system below. 

 

 

 

Improving

Visualizing the World - One of the challenges is that it is hard to view the entire world in the Master Scene. We can solve this by adding some debug drawing code.  The Gizmos for the CollisonRegions also helps to visualize this.

We can also add a editor button from the selected SubsceneTrigger to goto the associated scene.

There are some other methods that may be able to achieve this.  The documentation presents MergeScene.  This method sounds like it could work but I have not had any luck with it.  Hopefully, I can play around with it and get it to work.  The LoadSceneMode.Additive presented in (1) works perfectly.

Performance - If this is an issue you can grid align the World into uniformly sized cells.  This would avoid having to use the Collider component and reduce the number of Game Objects.  The subscenes in my game are non-uniformly spaced out so I am using the CirlceCollider2D. 

3D Implementation -  The same approach can be achieved in 3D.  Just use the properly 3D Collider Components and call backs (OnTrigger3D, etc).