Assemblies in Unity
Assemblies are useful in many ways like (Faster Compilation, Better Dependency Management, Platform-Specific Compilation, etc…)
We will check those in detail but first let’s add Assembly Definition Files by Right-click in Project window → Create → Assembly Definition.
For example, we have a project and has this Architecture.
Assets folder:
- Core Folder (
Core.asmdef): Zero dependencies. Every other folder depends on this one. - Systems Folder (
Systems.asmdef): Depends only on the Core folder. - UI Folder (
UI.asmdef): Sits on top. Depends on both Core and Systems. - Tests Folder (
Tests.asmdef): Test-only code. Never ships in your final build. - iOS Folder (iOSFeatures.asmdef) : Set to: Include ONLY iOS platform
- Android Folder (AndroidFeatures.asmdef) : Set to: Include ONLY Android platform
With doing that we actually achieve Faster Compilation because without Assembly Definition any changes you make in your scripts, Unity will recompile all scripts in the project, but now only the affected assembly and those that depend on it are recompiled.
Enforced Decouple Code (No Spaghetti Code):
- Scripts inside an assembly cannot access
internalmembers of another assembly. - Enforces architectural boundaries — e.g., If
UIassembly needs to talk toPlayerassembly, you have to explicitly define a dependency. This prevents you from writing tangled "spaghetti code" where everything references everything else, forcing you to write cleaner, more modular systems.
e.g: Assume the GameEvents lives in the Core folder, both UI assembly and Player assembly need to manually add Core.asmdef to their "Assembly Definition References" list in the Inspector. Now if we have a script called FloatEventChannelSO lives in the Core folder(Core.asmdef)
using System;
using UnityEngine;
[CreateAssetMenu(menuName = "Events/FloatEventChannel")]
public class FloatEventChannelSO : ScriptableObject
{
public Action<float> OnEventRaised;
public void RaiseEvent(float value)
{
OnEventRaised?.Invoke(value);
}
}Then give The Player (Shouter) script a public FloatEventChannelSO healthChannel; variable. Drag the SO asset into this slot. When damaged, call healthChannel.RaiseEvent(health);
Get Abdullah’s stories in your inbox
Join Medium for free to get updates from this writer.
And for The UI (Listener): Give your UI script the exact same public FloatEventChannelSO healthChannel; variable. Drag the same SO asset into this slot. Subscribe to healthChannel.OnEventRaised.
Now The Player doesn’t know about the UI and vice versa “Decoupling successfully achieved”.
NOTE: This example using the ScriptableObject does the actual job of decoupling the code. You could use that in a normal project without assemblies, and it would work great.
Adding assemblies just acts like a security guard. It physically forces you to keep that clean architecture, so you or another developer doesn’t accidentally ruin it later, while also giving you all those other benefits like faster compile times.
Platform-Specific Compilation:
- We can configure an assembly to only compile for specific platforms (e.g.: only for iOS, or exclude WebGL).
- Cleaner than scattering
#if UNITY_IOSpreprocessor directives everywhere.
The old way:
void DoSomething()
{
#if UNITY_IOS
iOSCamera.DoThing();
#endif
#if UNITY_ANDROID
AndroidPlugin.DoThing();
#endif
}but the Better Way by using Assembly Platform Filter Like we did above:
- iOS Folder (iOSFeatures.asmdef) : Set to: Include ONLY iOS platform
- Android Folder (AndroidFeatures.asmdef) : Set to: Include ONLY Android platform.
This exactly like you tell Unity only compile this entire folder of scripts when building for iOS. Ignore it completely for everything else.
There are many useful things by using Assemblies in Unity, we will discuss that in the future blogs. Thanks for reading.










