Architecture

51 packages and 218 declared dependencies, arranged so that no package can reach a system it did not ask for.

Foundry ships as a set of Unity packages, each with its own manifest, its own assembly definitions, and its own tests. A package declares what it depends on, and the architecture tests fail the build when an assembly reaches past that declaration. Every other property described here follows from that one rule.

Adoption is therefore incremental. You can take Inventory without Equipment, Armory without a player controller, and Persistence without Networking. A lower layer holds no reference to the layers above it, so a system you skip is absent from the build instead of sitting dormant in it.

Two packages sit underneath everything and depend on nothing at all. Messaging carries events and resolves services. Foundation carries the primitives, the definition registry, and the diagnostics gate. Two packages that need to talk without knowing about each other go through one of those two.

The shape

Six layers

Kernel

8 packages
combatcommondiagnostics.contractsfoundationmessagingnetworking.abstractionsstatsui.theming

Core

10 packages
armoryequipmentfoundrygameplayinputinteractioninventorynucleonpersistenceweaponmodding

Gameplay

12 packages
abilitiesaianimationconditionscraftingeconomyentityriglootobjectivesprogressionquantitiesterrain

Presentation

10 packages
audiocrosshairfeedbackfrontendlocalizationminimaprendering.corerendering.hdrprendering.urpvfx

Platform

4 packages
modkitnetworkingplatformplatform.steam

Tooling

7 packages
contentdemodiagnosticsextensionslocalization.authoringtestkitworkbench

Arrows read downward as “is built on”. A package may depend on anything in its own band or below it, and never on anything above.

Root packages

7 packages depend on nothing

These are the contracts. Everything above inherits their constraints, which is the argument for keeping them small.

com.zoa.diagnostics.contracts

Two types, no dependencies, so any package can publish a debug tab without depending on Nucleon.

com.zoa.foundation

Stable ids, the definition database, grid geometry, pooling, and the diagnostics gate every other package compiles against.

com.zoa.messaging

The publish/subscribe bus and service registry every other package talks through.

com.zoa.networking.abstractions

Dependency-free networking contracts: protocol DTOs, session policy, adapter seams, and the backend support matrix.

com.zoa.platform

One provider-neutral surface for auth, profiles, achievements, leaderboards, stats, friends, cloud saves, inventory, Workshop, DLC, overlay, and lobbies.

com.zoa.stats

Stat identifiers, modifiers, and the evaluation rule every gameplay package agrees on.

com.zoa.ui.theming

The design-token contract every ZOA surface renders through, owned by nobody and importable from anywhere.

Load bearing

Most depended upon

Change one of these and you change everything downstream. They are also the packages whose tests matter most.

Packages ranked by number of dependent packages
PackageTierDependents
foundationKernel41
messagingKernel27
ui.themingKernel12
inventoryCore10
commonKernel8
interactionCore8
networking.abstractionsKernel8
weaponmoddingCore8
persistenceCore7
animationGameplay6
combatKernel6
statsKernel6

Rules

How packages talk

Something happened: publish it on the event bus. A weapon that finishes reloading does not know the HUD exists, and the HUD does not know which weapon fired the event. Both know the message type, which lives in whichever package owns the concept.

Something is needed: resolve it from the service registry. A HUD component that needs theme data resolves IHudTheme rather than importing Equipment, which is why UI Theming is contract-only and depends on nothing.

Something must be authored: define it as a ScriptableObject. Definitions are the seam between designers and code across the whole stack, and the definition registry in Foundation is how a runtime system finds one without holding a hard reference to it.