Quick answer: Extract the types both assemblies need into a third “Core” or “Interfaces” assembly that both reference. Or invert one direction by raising events from one assembly that the other subscribes to. Define Constraints don’t fix this.

You add an asmdef to your Combat folder, another to UI, and reference each other. Compile fails: Assembly definition file Game.Combat references Game.UI, which references Game.Combat in a circular dependency. The fix is structural, not a flag flip.

The Symptom

Console error: “Assembly with name ‘Game.Combat’ has a circular reference with ‘Game.UI’.” All scripts in both assemblies become uncompilable. The Inspector shows red on every component.

What Causes This

Compile order. The C# compiler builds dependencies first; if A needs B and B needs A, neither can be compiled first. Unity rejects the configuration outright rather than picking arbitrarily.

The Fix Pattern: Extract Common Types

Most circular refs come from shared types. Solution: a Core or Interfaces assembly.

Game.Core           // IDamageable, DamageEvent, GameSettings
Game.Combat -> Game.Core
Game.UI     -> Game.Core

Game.Combat declares class Enemy : IDamageable. Game.UI accepts an IDamageable reference rather than an Enemy. Both reference Game.Core; neither references the other.

The Fix Pattern: Event Inversion

If Combat needs to tell UI “health changed”, inverting the dependency works:

// Game.Combat (no reference to UI)
public static class CombatEvents
{
    public static event Action<int> OnHealthChanged;
    public static void RaiseHealthChanged(int hp) => OnHealthChanged?.Invoke(hp);
}

// Game.UI (references Game.Combat)
public class HealthBar : MonoBehaviour
{
    void OnEnable()  => CombatEvents.OnHealthChanged += UpdateBar;
    void OnDisable() => CombatEvents.OnHealthChanged -= UpdateBar;
}

UI references Combat (one-way). Combat publishes events; UI subscribes. Cycle broken.

Detecting Circular Refs Before They Happen

Window → Analysis → Project Auditor (Unity 2022+). It maps assembly dependencies as a DAG. Cycles light up in red. Run before merging branches that touch asmdef structure.

Or open the .asmdef JSON manually and trace references in a graph tool.

Per-Folder Hierarchy

A clean asmdef structure looks like a tree:

Game.Core               (no deps)
  Game.Common         -> Core
    Game.Audio        -> Common
    Game.UI           -> Common
    Game.Combat       -> Common
      Game.AI         -> Combat, Common
  Game.Editor         -> Combat, UI, Common
    (Editor-only assembly, never referenced by runtime)

Lower nodes know about higher ones; never the reverse. Where they need to communicate, they use events or interfaces declared in Core/Common.

Verifying

After refactor, force a recompile (right-click any script → Reimport). Console clears the circular reference error. If new errors appear referencing missing types, those are the cases where you accepted a concrete type and now need to swap to the interface.

“Extract the shared into Core. Invert with events. Build a tree, not a cycle.”

Related Issues

For asmdef compile slowdowns, see compile slow. For Editor-only references, see editor-only asmdefs.

Common assembly. Events. The DAG flows downhill.