Make Unity more efficient with Assembly Definitions

Unity makes many things easy. You can just put a C# script anywhere in the Assets folder and Unity will automatically add it to the build. But, as is often the case, there is a better workflow.

First, organizing your scripts in a meaningful way is essential. Usually, you will put all your scripts into a “Scripts” or “Runtime” folder. And you will use subfolders to group related scripts.

Second, creating Assembly Definitions will improve your code base a lot.

What are Assembly Definitions?

By default, all Unity scripts are compiled in the predefined Assembly-CSharp.dll. Every script can access every other script.

With assembly definitions, you can split this up into multiple smaller assemblies. Classes in other assemblies can only be accessed if a reference to the assembly is defined.

Diagram of assembly definitions: Assembly-CSharp.dll references App.dll and ThridParty.dlls. App.dll references App.Models.dll and App.ViewModels.dll

Assembly definitions split the code into different modules or building blocks. Each module provides functionality in the form of public interfaces and classes. This type of modularization is a common software architecture technique to manage complex systems.

Why are Assembly Definitions important in Unity?

Faster reloads

Changing a script in a project requires Unity to rebuild the code libraries. While you won’t notice this in a small project, it can be very tedious in a large project. Whenever you change a script, Unity is blocked for a few seconds.

By using assembly definitions, the recompilation is only needed for the library of the changed script.

Cleaner code

A clear separation between different parts of a software project is crucial. For example, you don’t want your GUI scripts to have direct access to the business logic.

With a proper setup of references, the GUI scripts won’t see anything from the business logic. It’s just not possible that an undesired shortcut slips into the code.

Unit testing

Unit tests inside the Unity Test Runner only work with assembly definitions. A test suite requires its own assembly definition. And within that, it’s not possible to access any free floating scripts from the Assembly-CSharp.dll.

Platform dependent compilation

For each assembly, you can define in which platforms it is included. This enables platform-dependent code without excessive usage of #ifdefs.

An assembly can also target the Unity Editor. It’s not necessary anymore to put editor scripts into a top-level Editor-folder.

How are Assembly Definitions created?

Adding an assembly definition is simple: Select your script folder in your assets, right-click, and select Create/Assembly Definition.

This will add all scripts in the folder and subfolders to the assembly. Unless a subfolder contains its own Assembly Definition.

Inspector view of an assembly definition. The list of Assembly Definition References is highlighted.

You can define several settings for each assembly. E.g. its name, the target platforms, or whether it references the Unity engine itself.

If you want to use a script from another assembly, you have to add this assembly to the list of Assembly Definition References. It’s not possible to define cyclic references. That means, two assemblies can’t reference each other.

In the Unity manual, you find more detailed instructions on creating assembly definitions.

Visual Positioning System

Visual Positioning System

VPS is a localization technique based on imagery of the environment

Service Locator: a simple alternative to Singletons

Service Locator: a simple alternative to Singletons

Decouple clients of services from the concrete service implementation