The project is a modular template for co-op multiplayer games on Steam, made with Unity 6000.3.16f1. Networking runs on FishNet over Steam P2P, DI on VContainer, and every module is split into client, server and shared parts
This is what I start multiplayer projects from: the player, entities, items, triggers, HUD and menus are already in place, everything is synced over the network, and the core gameplay rules are covered by network tests
- Player: movement and ground check, a state machine for legs and hands, input handlers and an Operator mode - a free spectator camera
- Entities: health, damage and healing (dealers, receivers, zones), effects such as damage over time, destructible objects, explosions with knockback, health bars
- Items and inventory: inventory slots, factories for items and their views, interactable objects, surface types for hits
- Triggers: a data-driven condition → reaction system: spawn, despawn, enabling objects, animations, events, counters
- Levels: level zones, lighting and fog configs, spawn and despawn zones
- HUD and UI: cheat menu, hints, low-health popup, interaction prompts; main menu, pause, settings (volume, mouse sensitivity), loading screen
- Localization: English and Russian via Unity Localization
- FishNet + FishySteamworks: players connect over Steam P2P. In the Editor the transport can be switched to plain FishNet for quick local tests - the
UseSteamInEditorflag inSteamEditorConfig - Authoritative server: state travels through paired ForServer / ForClient broadcasts, wired together by
ServerBroadcastSynchronizer<T>,ClientBroadcastSynchronizerand synchronizer mediators for the owner, server and clients - Simple values use small synchronizers built on
SyncVarandServerRpc, plusRigidbodysync and a network timer - Scenes are loaded over the network through Addressables, and networked prefabs are registered from Addressables too
- Connecting: host and client buttons in the main menu, the client enters the host's SteamID (it is remembered), and the host can copy their own SteamID with one button
- DI on VContainer, with scopes split by lifetime:
PersistentServicesScope- for the whole app, registers everyIPersistentService,IPersistentFactory,IConfigsProviderServiceandIGameStateautomaticallyMatchSharedServicesScope,MatchServerServicesScope,MatchClientServicesScope- per matchOwnerPlayerLifetimeScope- for the local player
- Game state machine:
Bootstrap → MainMenu → Match → Exit, plus a separate server state machine - Modules live in
Assets/Modules, each split intoRuntime/Client,Runtime/ServerandRuntime/Sharedwith their own assemblies, so server code never ends up in the client and vice versa - Patterns: event bus, mediators, repositories, factories, object pools. Async code on UniTask, reactive code on UniRx
- Addressables with 26 groups and a loader that can fall back to
Resources
- Network play mode tests for damage, healing and effects: they spin up a real host and client through ParrelSync clones and are enabled with the
PARREL_SYNC_TESTSdefine - Unit tests for entity rules (
DoDamageTest,DoHealTest) on FluentAssertions
- Moving assets between Addressables and Resources to check the build both ways -
Tools/Core Module/Settings - Define symbol tools, find asset by GUID, missing prefabs finder, layer finder
- 4K game screenshot -
Tools/Make Game Screenshot 4K, and a shader preprocessor that strips unused variants
- Open the project in Unity 6000.3.16f1
- Start the Steam client:
steam_appid.txtis set to 480 - Valve's test app Spacewar, so you don't need your own App ID - Open the
Assets/Modules/AppModule/Runtime/Shared/Scenes/Initial.unityscene and press Play - To test multiplayer locally, open a second Editor through ParrelSync → Clones Manager: host in one, join with the host's SteamID in the other. To test over Steam right from the Editor, turn on
UseSteamInEditorinSteamEditorConfig
Build scenes: Initial, MainMenu, Game
Unity 6, C#, FishNet, FishySteamworks, Steamworks.NET, VContainer, UniTask, UniRx, Addressables, Input System, Unity Localization, URP, Animancer, DOTween, ParrelSync, FluentAssertions
Happy to hear any feedback or questions! :)