agentsclimarketplace

Unity multiplayer agent skills

Skill adevra/unity-multiplayer-agent-skills

Build real-time multiplayer games in Unity (C#) targeting mobile and WebGL2 browsers using Colyseus or Nakama game servers with WebSocket transport. Covers client-server architecture patterns, state synchronization (prediction, interpolation, rollback), Schema-based serialization, room/match lifecycle, matchmaking, reconnection, and cross-platform deployment. Use this skill whenever building Unity multiplayer games, integrating Colyseus or Nakama, handling WebGL2 networking constraints, optimizing multiplayer performance for mobile or browser, choosing between game server frameworks, or deploying multiplayer backends. Also trigger when the user mentions real-time networking in Unity, WebSocket client setup, authoritative servers, lobby/room systems, or network state sync — even if they don't say "multiplayer" explicitly.From its SKILL.md

Install
npx -y skills add adevra/unity-multiplayer-agent-skills

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its file declares

Copied from the file, not written here

The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

9.7 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it

Unity Multiplayer for Mobile & WebGL2

This skill guides you through building real-time multiplayer Unity games that ship to both mobile (iOS/Android) and WebGL2 browsers. The two primary server frameworks covered are Colyseus (automatic state sync, room-based) and Nakama (full game backend with auth, storage, matchmaking).

Decision tree — start here

1. Choose your server framework

Pick Colyseus when:

  • You need automatic state synchronization (schema-based binary deltas)
  • Your game is primarily room-based (lobbies, matches, sessions)
  • You want the fastest path to a working prototype
  • You'll handle auth/storage/leaderboards yourself or don't need them

Pick Nakama when:

  • You need built-in authentication (device, email, social, Steam)
  • You need persistent storage, leaderboards, tournaments, friends, groups, chat
  • You want a production-grade backend from day one
  • You're comfortable with manual state management via opcodes

→ For Colyseus details: read references/colyseus-integration.md → For Nakama details: read references/nakama-integration.md

2. Understand the WebGL2 hard constraints

WebGL builds cannot use raw TCP/UDP sockets, cannot use C# threads, and cannot host servers. All networking must go through WebSocket (or WebRTC). In production, HTTPS pages require wss:// connections.

The standard cross-platform pattern:

#if UNITY_WEBGL && !UNITY_EDITOR
    // WebSocket transport only — no UDP, no threads
    m_Driver = NetworkDriver.Create(new WebSocketNetworkInterface());
#else
    // Native platforms can use UDP for lower latency
    m_Driver = NetworkDriver.Create(new UDPNetworkInterface());
#endif

→ Full constraints and workarounds: read references/webgl2-constraints.md

3. Choose your WebSocket library

LibraryCostWebGLKey strength
NativeWebSocketFreeBundled with Colyseus SDK, v2.x auto-dispatches to main thread
Best WebSockets~€18WSS, compression, profiler integration
unity-websocketFreeMonoBehaviour API, built-in ping/RTT, zero WebGL code changes
Unity Transport (UTP)FreeOfficial Unity package, dual UDP+WebSocket listen

Avoid WebSocketSharp — it uses System.Net.Sockets and does not work in WebGL builds.

→ Full comparison and code examples: read references/websocket-networking.md

4. Pick your architecture pattern

GenrePatternWhat syncs
FPS / ActionClient-side prediction + server rewindState + input
MMO / RPGSnapshot interpolationState only
RTS / FightingDeterministic lockstep / rollbackInput only
Turn-basedRequest-responseActions only
Casual / SocialColyseus auto-sync or Nakama relayState or messages

→ Deep dive on each pattern: read references/architecture-patterns.md

Quick-start: Colyseus + Unity

Server (TypeScript):

import { defineServer, defineRoom, Schema, type, MapSchema } from "colyseus";

class Player extends Schema {
  @type("number") x: number = 0;
  @type("number") y: number = 0;
}

class GameState extends Schema {
  @type({ map: Player }) players = new MapSchema<Player>();
}

class GameRoom {
  onCreate() { this.setState(new GameState()); }
  onJoin(client) {
    this.state.players.set(client.sessionId, new Player());
  }
  onMessage(client, type, message) {
    const player = this.state.players.get(client.sessionId);
    if (type === "move") { player.x = message.x; player.y = message.y; }
  }
  onLeave(client) { this.state.players.delete(client.sessionId); }
}

defineServer({ rooms: { game: defineRoom(GameRoom) } });

Unity Client (C#):

using Colyseus;

var client = new Client("ws://localhost:2567");
var room = await client.JoinOrCreate<GameState>("game");

// Listen to player additions
var callbacks = Callbacks.Get(room);
callbacks.OnAdd(state => state.players, (sessionId, player) => {
    SpawnPlayer(sessionId, player);
    callbacks.Listen(player, p => p.x, (val, prev) => MovePlayer(sessionId));
});

// Send input
await room.Send("move", new { x = transform.position.x, y = transform.position.z });

→ Full Colyseus integration guide: references/colyseus-integration.md → Server template: assets/colyseus-room-template.ts → Client template: assets/unity-colyseus-manager.cs

Quick-start: Nakama + Unity

Server (TypeScript runtime):

const matchInit: nkruntime.MatchInitFunction = (ctx, logger, nk, params) => {
  return { state: { players: {}, tick: 0 }, tickRate: 20, label: "" };
};

const matchLoop: nkruntime.MatchLoopFunction = (ctx, logger, nk, dispatcher, tick, state, messages) => {
  for (const msg of messages) {
    const data = JSON.parse(new TextDecoder().decode(msg.data));
    state.players[msg.sender.userId] = { x: data.x, y: data.y };
  }
  dispatcher.broadcastMessage(1, JSON.stringify(state.players));
  return { state };
};

Unity Client (C#):

using Nakama;

var client = new Client("http", "127.0.0.1", 7350, "defaultkey",
    UnityWebRequestAdapter.Instance);
var session = await client.AuthenticateDeviceAsync(SystemInfo.deviceUniqueIdentifier);

var socket = client.NewSocket(useMainThread: true);
await socket.ConnectAsync(session);
var match = await socket.CreateMatchAsync();

// Send state
await socket.SendMatchStateAsync(match.Id, 0,
    System.Text.Encoding.UTF8.GetBytes(JsonUtility.ToJson(position)));

// Receive state
socket.ReceivedMatchState += (matchState) => {
    var data = System.Text.Encoding.UTF8.GetString(matchState.State);
    ApplyState(matchState.UserPresence.UserId, JsonUtility.FromJson<Position>(data));
};

→ Full Nakama integration guide: references/nakama-integration.md → Server template: assets/nakama-match-handler-template.ts → Client template: assets/unity-nakama-manager.cs

Performance checklist

When optimizing for mobile + WebGL2, follow this priority order:

  1. Reduce what you send — Delta compression, quantization, smallest-three quaternion encoding. Only sync changed data. Use NetworkVariable for persistent state, RPCs for events.
  2. Reduce how often you send — 20-30 ticks/second is optimal. Use interpolation to smooth gaps. Colyseus defaults to 20Hz patchRate.
  3. Reduce who receives — Interest management / area-of-interest filtering. Far entities get lower update rates or are culled entirely.
  4. Use binary serialization — MessagePack for C# is the best general choice (10-100x faster than JSON, compact). Avoid JSON in production hot paths.
  5. Pool everything — Object pooling for network messages, byte arrays, collections. WebGL GC runs only once per frame; mid-frame allocations risk OOM.
  6. Batch on mobile — Minimize cellular radio activations. Front-load transfers, avoid polling patterns. Offer 30 FPS option.

→ Detailed optimization guide: references/performance-optimization.md

Deployment overview

Both Colyseus and Nakama deploy via Docker. For production:

  • Nginx reverse proxy with WebSocket upgrade headers
  • SSL/TLS required for WebGL clients (wss://)
  • Colyseus scaling: Redis for presence + driver, PM2 in fork mode
  • Nakama scaling: CockroachDB cluster, multi-node Nakama with gossip discovery

→ Full deployment guides: references/deployment-guides.md

Reference files index

Read these as needed — don't load all at once:

FileWhen to read
references/architecture-patterns.mdChoosing network topology, state sync strategy, or ECS networking
references/colyseus-integration.mdSetting up Colyseus server, Unity SDK, rooms, schema, matchmaking
references/nakama-integration.mdSetting up Nakama server, Unity SDK, auth, multiplayer, storage
references/websocket-networking.mdChoosing/configuring WebSocket library, reconnection logic
references/webgl2-constraints.mdUnderstanding WebGL2 limitations, conditional compilation patterns
references/performance-optimization.mdNetwork bandwidth, serialization, GC, mobile battery, object pooling
references/deployment-guides.mdDocker, Nginx, SSL, Redis, scaling, managed hosting options

Asset templates index

FilePurpose
assets/colyseus-room-template.tsProduction-ready Colyseus room with auth, reconnection, clock sync
assets/nakama-match-handler-template.tsAuthoritative Nakama match with tick loop, presence tracking
assets/unity-colyseus-manager.csUnity singleton managing Colyseus connection, room join, state callbacks
assets/unity-nakama-manager.csUnity singleton managing Nakama client, socket, auth, match lifecycle
assets/unity-websocket-client.csStandalone WebSocket client with exponential backoff reconnection

What ships with it: 19 files

142.9 KB alongside SKILL.md, 3 of them executable

scripts/

Keep looking

Skills are one crate of 326,852. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.