Imagine working on a large Unity game containing hundreds of scripts.
The project includes vehicle controllers, character systems, inventory management, user interfaces, AI behavior, multiplayer features, and custom Editor tools.
You modify a small utility script.
Unity starts compiling.
Instead of returning to development immediately, you wait while the Editor processes code changes.
As the project grows, these interruptions can become frustrating, particularly when developers frequently switch between scripting and testing.
Unity Assembly Definition Files offer a way to organize scripts into separate compiled assemblies and control which parts of a project depend on one another.
This can reduce unnecessary recompilation and make complex projects easier to maintain.
However, assembly definitions are not an automatic performance solution. Incorrect configuration can introduce missing-reference errors, circular dependencies, and additional maintenance work.
This guide explains nine practical techniques for implementing assembly definitions in Unity projects.
1. Understand How Unity Assembly Definition Files Work
Before creating assembly definitions, understand how Unity compiles scripts.
In a conventional Unity project, many scripts are compiled into predefined assemblies.
One familiar example is:
Assembly-CSharp.dll
Unity also uses other predefined assemblies for specific scripting categories.
This arrangement is convenient for smaller projects because developers can create scripts without configuring assembly references.
However, placing a large amount of code inside one assembly has limitations.
When a script changes, Unity may need to recompile the assembly containing that script.
A large predefined assembly can therefore create unnecessary compilation work during development.
What Is an Assembly Definition File?
An Assembly Definition File is a Unity asset with the extension:
.asmdef
It defines a separate managed assembly for scripts located within its folder hierarchy.
For example:
Assets/
Game/
Inventory/
Game.Inventory.asmdef
InventoryManager.cs
InventoryItem.cs
InventoryUI.cs
Unity compiles the scripts associated with Game.Inventory.asmdef into a separate assembly.
The precise compilation behavior depends on the assembly dependency graph.
The official Unity assembly documentation explains how assemblies provide control over code organization, references, and recompilation.
Why Does This Matter?
Separating scripts into appropriate assemblies can help developers:
- Reduce unnecessary recompilation.
- Define clearer code dependencies.
- Separate runtime and Editor functionality.
- Improve modularity.
- Make systems easier to maintain.
- Support reusable packages.
These advantages become particularly relevant when multiple developers work on the same Unity project.
2. Identify Which Systems Should Become Separate Assemblies
One of the biggest mistakes developers make is creating assembly definitions without first understanding their project architecture.
Not every folder needs a separate assembly.
A small prototype containing a few scripts may not benefit meaningfully from additional assembly boundaries.
Larger projects require more deliberate organization.
Example: Simulation Game Architecture
Consider a hypothetical supermarket simulation containing:
- Product inventory
- Customer AI
- Shelf interactions
- Store economy
- Player controls
- UI systems
- Save functionality
A possible structure is:
Assets/
Game/
Core/
Game.Core.asmdef
Inventory/
Game.Inventory.asmdef
Economy/
Game.Economy.asmdef
Customers/
Game.Customers.asmdef
UI/
Game.UI.asmdef
Editor/
Game.Editor.asmdef
Each assembly represents a meaningful responsibility.
For example, the inventory system may depend on shared interfaces and item identifiers defined in the Core assembly.
The UI assembly may reference inventory functionality to display product information.
Avoid Excessive Fragmentation
Creating one assembly for every small script is rarely useful.
Too many assemblies can increase configuration complexity and make dependency management harder.
Instead, group scripts according to stable responsibilities.
A useful principle is:
Create assembly boundaries around systems that can evolve independently.
For example, a reusable inventory system may deserve its own assembly.
A collection of three tightly connected helper scripts may not.
Think About Future Maintenance
Before creating an assembly, ask:
Does this system have a clear responsibility?
Will other systems need to reference it?
Can it be tested independently?
Could it be reused in another project?
Would separating it reduce unnecessary dependencies?
These questions help prevent architecture from becoming unnecessarily complicated.
3. Create Your First Unity Assembly Definition File
Unity provides an Editor workflow for creating assembly definitions.
The following steps apply to the documented Unity 6 workflow.
Step 1: Organize Your Scripts
Create a folder containing the scripts you want to compile together.
For example:
Assets/Game/Inventory/
Move the relevant inventory scripts into that folder.
Step 2: Create the Assembly Definition
In Unity’s Project window:
Right-click → Create → Scripting → Assembly Definition
Name the asset:
Game.Inventory
Unity creates an .asmdef asset.
Step 3: Inspect the Assembly
Select the new asset.
The Inspector displays assembly configuration options.
Depending on the Unity version, these include assembly references, platform settings, and other compilation controls.
Step 4: Configure Dependencies
If your inventory scripts depend on types defined in another custom assembly, add the appropriate reference.
For example:
Game.Inventory may reference Game.Core.
Step 5: Apply and Compile
Apply the configuration and allow Unity to recompile.
Check the Console for missing references or other compilation errors.
Unity’s Creating assembly assets documentation confirms the Assets → Create → Scripting workflow and explains how assembly definitions include scripts within their folder hierarchy. Unity Documentation
Important Folder Behavior
An assembly definition generally includes scripts in its folder and child folders unless another assembly definition or assembly reference changes that association.
For example:
Inventory/
Game.Inventory.asmdef
InventoryManager.cs
Runtime/
InventoryRuntime.cs
Both scripts can belong to the same assembly.
However, placing another .asmdef inside Runtime creates a separate assembly boundary.
Understanding this behavior is important when reorganizing existing projects.
4. Manage Assembly References Correctly
Assembly references determine which compiled assemblies can access types from other assemblies.
Consider this structure:
Game.Core
↑
Game.Inventory
↑
Game.UI
Here, Game.Inventory references Game.Core.
Game.UI references Game.Inventory.
This allows UI code to use inventory functionality without requiring Core to depend on UI.
Why Dependency Direction Matters
A common architectural problem occurs when unrelated systems depend directly on one another.
For example:
- Inventory depends on UI.
- UI depends on inventory.
This can create a circular dependency.
Circular assembly references are not a valid dependency structure.
Better Architecture
Move shared contracts into a lower-level assembly.
For example:
Game.Contracts
↑
|
Game.Inventory
↑
|
Game.UI
Alternatively, both Inventory and UI may reference the shared Contracts assembly.
The appropriate structure depends on the responsibilities of each system.
Practical Example
Suppose a shop interface needs to display inventory quantities.
Instead of making the inventory system directly control UI components, expose an inventory interface or read-only API.
The UI can then consume that API.
This keeps gameplay systems less dependent on presentation code.
Use Assembly References Deliberately
Do not add every assembly as a reference simply to eliminate compilation errors.
That approach can recreate the tightly coupled architecture you were trying to improve.
Instead, investigate why a dependency exists.
Unity documents assembly reference configuration and dependency behavior in its official assembly organization guide.
5. Separate Runtime and Editor Code
Unity projects often contain scripts intended only for development tools.
Examples include:
- Custom Inspectors
- Editor windows
- Asset validation utilities
- Scene-generation tools
- Batch-processing scripts
- Custom import workflows
These scripts may use the UnityEditor namespace.
However, UnityEditor APIs are not intended for ordinary player runtime code.
Recommended Structure
Game/
Runtime/
Game.Runtime.asmdef
Editor/
Game.Editor.asmdef
The Runtime assembly contains gameplay functionality.
The Editor assembly contains tools used inside the Unity Editor.
Configure Editor-Only Assemblies
Create an assembly definition for Editor scripts.
In the assembly’s platform configuration, restrict it to the Editor platform.
If Editor tools need access to runtime classes, configure the Editor assembly to reference the Runtime assembly.
The dependency direction should be:
Editor → Runtime
Runtime code should not depend on Editor-only code.
Why This Is Important
Incorrect separation can produce build errors.
A script may compile successfully inside the Editor but fail when building for Android, Windows, or another platform.
This often happens when runtime assemblies accidentally depend on Editor-only functionality.
Unity’s assembly creation documentation explains how Editor assemblies and platform-specific assemblies are configured.
Practical Tip
When creating custom Editor tools, keep the code that performs reusable operations separate from the code that displays Editor interfaces.
For example, a texture validation algorithm might belong to a reusable utility assembly, while the custom Editor window belongs to an Editor-only assembly.
This can make the implementation easier to test and maintain.
6. Use Assembly Definition References When Appropriate
Unity provides another related asset type:
Assembly Definition Reference
Its extension is:
.asmref
An assembly definition creates an assembly.
An assembly definition reference associates scripts in another folder with an existing assembly.
Example
Suppose your inventory system has scripts in multiple folders.
Game/
Inventory/
Game.Inventory.asmdef
SharedInventoryComponents/
InventoryPickup.cs
You may want InventoryPickup.cs to belong to the existing inventory assembly without moving the script into the Inventory folder.
An Assembly Definition Reference can support that organization.
When Is This Useful?
Assembly Definition References can help when:
- Scripts must remain in separate folder locations.
- Multiple folders logically belong to one assembly.
- A project contains specialized organizational requirements.
- You want to avoid creating unnecessary additional assemblies.
Important Distinction
An .asmref does not create another independent compiled assembly.
It associates scripts with an assembly defined elsewhere.
Unity’s Creating assembly assets guide explains the difference between .asmdef and .asmref assets.
Avoid Using References to Hide Poor Organization
If a project requires numerous assembly references scattered throughout unrelated folders, review whether the folder structure itself should be improved.
Assembly references are useful tools, but they should support a deliberate architecture.
7. Organize Test Assemblies for Reliable Development
Testing becomes increasingly important as projects grow.
A game may contain systems for:
- Inventory transactions
- Player progression
- Mission completion
- Vehicle upgrades
- Economy calculations
- Save-data validation
Some of these systems can be tested without loading an entire gameplay scene.
Unity supports dedicated test assemblies.
Why Separate Tests?
Keeping tests separate from production code helps developers maintain clear responsibilities.
It also supports workflows where test-related dependencies should not be part of ordinary runtime assemblies.
Example Structure
Game/
Runtime/
Game.Runtime.asmdef
Tests/
Editor/
Game.Editor.Tests.asmdef
Runtime/
Game.Runtime.Tests.asmdef
Actual test assembly configuration depends on the installed testing packages and whether the tests run in Edit Mode or Play Mode.
Important Configuration
Test assemblies require the appropriate test-related references and settings.
Unity’s assembly creation documentation explains that test assemblies are treated differently from ordinary application assemblies and are not included in standard player builds by default. Unity Documentation
Practical Example
A supermarket game might contain an economy system that calculates product purchases.
A test could verify that:
- The purchase succeeds when sufficient currency is available.
- The purchase fails when funds are insufficient.
- Inventory quantities update correctly.
- Invalid product IDs are rejected.
These tests can help detect regressions after source-code changes.
However, automated tests do not replace gameplay testing.
For broader release validation, GamePro Studio’s Unity Game QA Checklist provides complementary guidance on testing workflows.
8. Troubleshoot Common Assembly Definition Errors
Assembly definitions can introduce compilation problems when references or platform settings are incorrect.
Understanding the most common errors makes troubleshooting easier.
Error: Type or Namespace Cannot Be Found
A script references a class from another assembly, but the required assembly reference is missing.
Possible solution: Inspect the assembly containing the missing type and configure the appropriate reference.
Also verify that the class and namespace names are correct.
Error: Circular Assembly References
Two assemblies depend on each other.
Possible solution: Review the dependency graph.
Move shared interfaces or contracts into a lower-level assembly when appropriate.
Error: Editor Code Fails in Player Builds
Runtime code references Editor-only APIs or assemblies.
Possible solution: Separate Editor and Runtime code, then review platform restrictions and dependency direction.
Error: Third-Party Package Types Are Missing
Your assembly depends on a package or plugin that is not referenced correctly.
Possible solution: Check whether the dependency uses its own assembly definition or precompiled DLL.
Review the relevant reference settings rather than assuming every package can be referenced identically.
Error: Scripts Compile in One Assembly but Not Another
The scripts may rely on implicit access available in the original predefined assembly.
After moving them into a custom assembly, explicit references may be required.
Possible solution: Identify the actual dependency and add the appropriate assembly reference.
Troubleshooting Checklist
When an assembly error appears, investigate the following in order:
- Identify the script producing the error.
- Determine which assembly contains that script.
- Identify the assembly containing the required type.
- Check whether the reference is configured.
- Review platform restrictions.
- Inspect package dependencies.
- Check for circular references.
- Recompile and verify the result.
Avoid randomly deleting assembly definitions or changing multiple settings simultaneously.
Make one controlled change at a time.
9. Measure Compilation Improvements Before and After Changes
Assembly definitions can reduce unnecessary recompilation, but the actual benefit depends on project structure.
A poorly designed assembly graph may provide little improvement.
For example, if a frequently modified shared assembly is referenced by many other assemblies, changing it may still trigger substantial recompilation.
Establish a Baseline
Before restructuring the project, record how long representative script changes take to compile.
Choose several scenarios:
- Modify an isolated gameplay utility.
- Modify a frequently used shared interface.
- Modify a UI script.
- Modify an Editor-only tool.
Record the compilation behavior for each scenario.
Apply Assembly Boundaries
Separate appropriate systems into assemblies.
Configure dependencies and resolve compilation errors.
Repeat the Same Tests
Perform comparable changes and observe compilation times.
Avoid drawing conclusions from a single measurement.
Editor caching, project state, and other factors can affect the results.
Understand What Assembly Definitions Do Not Solve
Assembly definitions do not automatically:
- Increase gameplay FPS.
- Reduce draw calls.
- Optimize textures.
- Improve GPU rendering.
- Fix garbage collection spikes.
- Reduce every type of Editor delay.
Their primary benefits concern code organization, dependencies, and compilation boundaries.
For runtime performance issues, GamePro Studio’s Unity Mobile Game Optimization Guide covers a different set of techniques.
Maintain the Architecture
As new features are added, periodically review whether the assembly structure still makes sense.
Avoid creating unnecessary dependencies simply because a new feature needs access to another system.
A well-maintained assembly structure can support long-term development more effectively than a complicated structure created once and never reviewed.
Practical Example: Modular Architecture for a Unity Racing Game
Consider a hypothetical racing game containing vehicle physics, AI opponents, garage customization, progression, and UI systems.
The project initially stores most gameplay scripts inside the default Assembly-CSharp assembly.
As the codebase grows, compilation interruptions become more noticeable.
A development team decides to review its assembly structure.
Stage 1: Identify Independent Systems
The team identifies several functional areas:
- Core utilities
- Vehicle systems
- Racing AI
- Garage customization
- UI
- Editor tools
Stage 2: Define Assembly Boundaries
The team creates separate assemblies for suitable systems.
Game.Core
Game.Vehicles
Game.RacingAI
Game.Garage
Game.UI
Game.Editor
Stage 3: Review Dependencies
The vehicle system references shared Core functionality.
The racing AI references vehicle interfaces.
The garage system accesses vehicle configuration data.
The UI references public APIs exposed by the relevant gameplay systems.
Stage 4: Separate Editor Tools
Custom vehicle configuration tools are placed in an Editor-only assembly.
Stage 5: Validate Builds
The team verifies that the game still compiles and runs on its intended target platforms.
Stage 6: Compare Compilation Behavior
The team repeats representative script changes and compares compilation times with the original project.
Stage 7: Document the Structure
A short architecture document explains:
- Assembly responsibilities
- Dependency direction
- Shared interfaces
- Editor-only functionality
- Testing requirements
This example illustrates a possible production workflow. It does not represent measured results from a specific GamePro Studio project.
Common Unity Assembly Definition Files Mistakes
Creating Too Many Assemblies
Excessive fragmentation can make project configuration harder to maintain.
Create meaningful boundaries rather than one assembly per small folder.
Adding Every Possible Reference
This weakens dependency control and can recreate tightly coupled systems.
Reference only the assemblies actually required.
Ignoring Dependency Direction
A gameplay system should not depend on unrelated presentation or Editor systems without a clear architectural reason.
Moving Scripts Without Reviewing References
Scripts that previously compiled together may require explicit assembly references after separation.
Plan the migration carefully.
Mixing Editor and Runtime Code
Editor-only dependencies can cause player-build failures when they are not separated correctly.
Assuming Faster Compilation Means Better FPS
Assembly organization primarily improves development workflows and maintainability.
Runtime performance must be measured independently.
Restructuring Without Version Control
Large assembly changes can affect many scripts simultaneously.
Use version control and verify a clean build before making extensive modifications.
Unity Assembly Definition Files vs Default Assemblies
| Feature | Default Assemblies | Custom Assembly Definitions |
|---|---|---|
| Initial setup | Simple | Requires configuration |
| Dependency control | Limited | Explicit references |
| Compilation boundaries | Broad predefined groups | Developer-defined groups |
| Modularity | Possible, but less enforced | Easier to enforce |
| Editor/runtime separation | Supported through predefined behavior | More explicit control |
| Large project maintenance | Can become difficult | Can improve with good architecture |
| Best use case | Small or straightforward projects | Growing, modular projects |
Neither approach is automatically superior for every project.
Small prototypes may benefit from simplicity.
Larger projects may benefit from carefully designed assembly boundaries.
Conclusion
Unity Assembly Definition Files can help developers organize large C# codebases, establish clearer dependencies, and reduce unnecessary recompilation during development.
The most important practices are to create meaningful assembly boundaries, manage references carefully, separate Editor and runtime code, and measure compilation behavior before and after changes.
Assembly definitions should support a clean architecture rather than become another source of complexity.
For studios developing mobile, PC, VR, or simulation games, maintainable source-code organization can also simplify future updates, outsourcing, and project handoffs.
GamePro Studio provides Unity development, source-code customization, optimization, and cross-platform game production services.
Explore GamePro Studio services or contact GamePro Studio to discuss project-specific development requirements.
Frequently Asked Questions
What are Unity Assembly Definition Files?
Unity Assembly Definition Files are .asmdef assets that allow developers to organize scripts into separately compiled assemblies and configure dependencies between them.
Do assembly definitions make Unity compile faster?
They can reduce unnecessary recompilation when scripts are divided into appropriate assemblies with well-designed dependencies. Actual improvements depend on the project structure.
Should every Unity project use assembly definitions?
Not necessarily. Small projects may work well with predefined assemblies. Larger or more modular projects are more likely to benefit from explicit assembly organization.
Can assembly definitions improve game FPS?
Assembly definitions primarily affect code organization and compilation workflows. They should not be treated as a direct gameplay FPS optimization technique.
What is the difference between .asmdef and .asmref?
An .asmdef creates a separate assembly. An .asmref associates scripts in another folder with an existing assembly.