Chuyển tới nội dung chính

Architecture

Layers​

ProjectV Client: scenes, views, gameplay
-> IProjectV*Presenter + snapshots com.silvertiger.projectv.unity
(VContainer scope) com.silvertiger.projectv.integrations.vcontainer
(native Google sign-in) com.silvertiger.projectv.integrations.google
-> ProjectV contracts, admission, state store com.silvertiger.projectv.client
-> ProjectV Nakama binding com.silvertiger.projectv.client.nakama
-> Shared SDK com.silvertiger.crosssdk.{core,contracts,auth,state,
readmodel,lobby,realtime,nakama,unity}
-> ProjectV Nakama V3 (projectz-nakama v3 + nakama-core-module)
PackageResponsibility
projectv.clientBackend-neutral contracts, ProjectVAdmissionGate, ProjectVStateStore, typed capability clients, composition and lifecycle. No Unity, no raw RPC
projectv.client.nakamaThe only package that binds typed operations to Nakama transport; strict decoders; mission realtime binding. Exports no public consumer types
projectv.unityStandard Unity runtime: ProjectVSettings, ProjectVSdkHost, presenters, Setup tooling, diagnostics
projectv.integrations.vcontainerProjectVPresentationLifetimeScope and the scene-scope bases. Borrows the root; owns no infrastructure
projectv.integrations.googleNative Android/iOS and Editor Google authentication
projectv.integrations.purchasingUnity IAP v5 orchestration; not in the current Client profile (IAP disabled)

Only SilverTiger.ProjectV.Unity and SilverTiger.ProjectV.Unity.VContainer are auto-referenced by consumers; every other assembly is explicitly referenced, so game code cannot reach it by accident.

Runtime sequence​

ProjectVSdkHost (one persistent root) builds the runtime from ProjectVSettings
-> StartAsync: admission (app/config, app/version) — fail closed on
maintenance, update, contract/capability drift
-> restore secure session (optional) or AwaitingLogin
-> authenticate (device, password, Google, Apple)
-> hydrate with one player/sync: every syncable snapshot into the read-model cache
-> load the mission and character catalogs in the background
-> realtime only when a feature needs it
-> presenters publish snapshots; screens render only changed views;
commands return projected state
-> on returning to the foreground: player/sync again
-> LogoutAsync: stop realtime, clear state, logout session

DisposeAsync ends the runtime's lifetime, not the account session; a scene unload is not a logout.

State​

ProjectVStateStore keeps immutable, revisioned per-capability snapshots and the shared ISessionEpochOwner. Refreshes coalesce; reads and mutations capture the session epoch; logout advances it before any await, so results for an old account are dropped. Mutations apply complete server projections in one batch (see Mutation projections).

Server reads go through the Shared SDK read-model cache (SessionReadModelStore). Each read model has a descriptor in ProjectVCacheDescriptors with a fresh and a stale window taken from the backend contract's read_models: five minutes fresh for the player capabilities that every mutation projects (characters, loadout, progression, skills, equipment, skins, economy, inventory, mission status, progress and history), a day for the character catalog and the mission catalog payload (whose manifest is checked every five minutes), and shorter windows for stamina and view state. ProjectVReadModelProjectionSink writes mutation projections and the player/sync snapshots into the same cache, so a screen opened afterwards reads them without a request. Concurrent reads of one key join one fetch.

Request budget​

ActionRequests
Startup or foreground hydration1 (player/sync), plus background catalog loads after startup
Opening Lobby, Campaign or Character within the fresh window0; Character reads the skill tree and cast skills on its first open, then keeps them fresh for five minutes
Any projected mutation (purchase, upgrade, level-up, mission transition)1, no follow-up reads
Beginning a mission1 (mission/admit), plus a reread of any admission fence older than its fresh window

A change that adds a request to one of these rows needs a reason in its pull request.

Admission​

ProjectVAdmissionGate follows the major.minor contract revision: it admits a server of the same major whose minor is at least the client's and that still offers every client capability; a newer major is UpdateRequired; older servers, schema or capability drift, maintenance and minimum-version updates fail closed. Readers ignore unknown response members and map unknown enums to Unknown, so additive server changes keep released clients working.

Extension rule​

New features are vertical slices: server operation and contract → typed client and decoder → Nakama binding → projection policy and state slot → presenter and snapshot → tests → binary release → Client UI. See Add a presenter.