Open-source project
PurrNet/PurrNet avatar
PurrNet/PurrNet

PurrNet: Unity networking where Instantiate() is the whole API

A Purrfect Unity Networking Solution

696 stars84 forksC#MIT

At a glance

What is it?
PurrNet is a MIT licensed Unity networking framework that generates the network plumbing at compile time through an IL post-processor, so spawning a networked object is an ordinary Instantiate call, with per-object network rules, network modules, client-side prediction and a set of transports. It suits a Unity studio that wants a different abstraction from Netcode for GameObjects, and it is a young framework on a beta release line.
Who is it for?
PurrNet is worth evaluating for a Unity team that finds the usual network object lifecycle noisy, because the entire premise is that spawning becomes an Instantiate call and RPCs become an attribute on a method, and because the network rules system moves authority from hard-coded checks into a per-object policy you can change without touching game code.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The pitch is one line of code and no registration

The argument PurrNet makes is about the shape of your game code, and it is worth taking seriously before the feature list.

You write Unity code and PurrNet makes it multiplayer. The example is a networked spawn, and the comment in the code says it plainly: that is the whole API.

csharp
// This is a networked spawn. That's the whole API.
_player = Instantiate(playerPrefab);

What is absent is the point. There is no NetworkServer.Spawn(), no manual registration, no serializer boilerplate and no ID plumbing. PurrNet's IL post-processor generates all of it at compile time.

So the design decision is where the ceremony goes. Instead of you calling a spawn API and registering a type and wiring a serializer, the framework inspects your compiled assembly and generates the network layer for you. The consequence is that a networked object in your project looks like an ordinary Unity object, and the network behaviour is a property of the build rather than of the source.

That also has a cost that follows from the design. A compile-time post-processor is a dependency on the Unity build pipeline and on the framework understanding your code, and the migration guides for coming from another solution exist because the abstraction is genuinely different rather than a rename.

The framework is MIT licensed and open source, with no seat licences, no CCU tax and no revenue share, and the readme states that you can ship a commercial game with it and the authors ask nothing in return. It is also on the Unity Asset Store, and the site has a section for studios.

Installing from a git branch, which is unusual and deliberate

The install instructions are through Unity's Package Manager with a Git URL, and the URL carries a branch reference. The requirement is Unity 2022 or newer.

The release branch is described as stable and recommended:

bash
https://github.com/PurrNet/PurrNet.git?path=/Assets/PurrNet#release

The dev branch is more up to date and more prone to breaking changes:

bash
https://github.com/PurrNet/PurrNet.git?path=/Assets/PurrNet#dev

Or through OpenUPM:

bash
openupm add dev.purrnet.purrnet

And from the Asset Store, where the documentation notes the versions lag behind.

The path parameter, /Assets/PurrNet, tells the Package Manager where the package lives inside the repository, and the branch fragment at the end is what makes this a branch-tracking install rather than a tag. That is a distribution model with consequences: your Unity project holds a reference to a branch, so a change on that branch reaches your project when Unity resolves it, and there is no version number in your manifest to pin the API you built against.

For a studio that wants a stable line, the release branch is the one to track, and the honest way to use this is to decide up front which branch you follow and to check the changelog when you move. The release history supports treating the release branch as the safe one: the recent tags are all 1.25.0 betas, with beta.5 on 2026-10-20, beta.4 on 2026-10-19 and beta.3 on 2026-10-17, and the default branch of the repository is dev, with the last push on 2026-10-20.

Spawning works because the rules decide who is allowed to do it

The spawning example is short enough to be complete, and the interesting part is what follows it.

csharp
[SerializeField] GameObject playerPrefab;

private GameObject _player;

void SpawnPlayer()
{
    _player = Instantiate(playerPrefab);
}

void DespawnPlayer()
{
    Destroy(_player);
}

The code says nothing about networking, and the documentation says the rest is handled for you. Then it explains the mechanism, which is the Network Rules system. Depending on which rules you pick, clients can even spawn and despawn their own objects, with no changes to that code. The rules are a per-object policy for who may spawn, despawn, own, observe and call, and the framing is that it can be server-strict or client-convenient, your call, with no code changes.

So the authority model is configuration rather than code. That is the real design difference from a framework where the server owns spawning and the client asks.

There is also a scene-level path. You can drag and drop prefabs into the scene and have them spawn automatically, as long as they have a NetworkIdentity component attached and are part of your NetworkPrefabs list. Drag prefabs into the scene and they spawn too, which is the same Unity-native claim as the Instantiate example, applied to the scene rather than to code.

The whole thing works because PurrNet's IL post-processor generates all of it at compile time, so there is no runtime registration step for you to miss.

RPCs cover the cases other frameworks make you choose between

The RPC section is the most detailed part of the documentation, and the reason is that PurrNet does not make you pick a single calling convention.

There are TargetRPCs, ServerRPCs and ObserverRPCs, and depending on your network rules these can all be called directly by clients too.

csharp
[ServerRPC]
void DoSomethingOnServer()
{
    Debug.Log("Doing something on the server!");
}

Static RPCs are supported, which matters because a static method has no instance to hang state on:

csharp
[ServerRPC]
static void DoSomethingOnServer()
{
    Debug.Log("Doing something on the server!");
}

Awaitable RPCs are supported, with a Task return:

csharp
[ServerRPC]
static Task<int> GetMyNumber()
{
    return Task.FromResult(42);
}

UniTask integration is supported in the same shape:

csharp
[ServerRPC]
static UniTask<int> GetMyNumber()
{
    return UniTask.FromResult(42);
}

Coroutine RPCs are supported as well, and the documentation asks the question itself, why not coroutine RPCs, and answers with one:

csharp
[ServerRPC]
static IEnumerator DoSomethingOnServer()
{
    yield return new WaitForSeconds(1);
    Debug.Log("Doing something on the server!");
}

And generic RPCs are supported:

csharp
[ServerRPC]
static void DoSomethingOnServer<T>(T value)
{
    Debug.Log($"Doing something on the server with {value}!");
}

These can be combined, so a static RPC that returns a value and is awaitable and generic is a valid thing to write. The cost of that coverage is a large surface, and the practical question for a team is which of these they will actually use, because every variant is part of the generated code the post-processor has to get right.

Network modules nest, and SyncVars are built on them

Network Modules are the extension mechanism, and the framing is that you compose networked behaviour out of nestable, reusable, generic modules, and every built-in feature is one.

SyncVars are built using Network Modules, and you can create your own to add custom logic to your networked objects. The documentation calls this a whole new world of possibilities for modularity and extensibility.

The modules can also be nested inside each other, and the example makes the point by saying that for the next example a SyncVar<int> could have been used, since that is itself a NetworkModule, but is not used for demonstration purposes.

The other extensibility points in the feature table are worth separating out, because they are different mechanisms. Client-side prediction is delivered by PurrDiction, which gives rollback prediction with optional determinism, so determinism is opt-in rather than assumed. Reconnection is built in through cookie-based identity, so a player who comes back gets their own state rather than a fresh spawn.

Serialization is described as real serialization, with compile-time generated packers, delta compression, and a hand-drivable BitPacker when you want the bytes. The BitPacker is the interesting escape hatch, because it means a project that has to match an existing binary protocol can drive the packing itself rather than accepting the generated one.

The platform reach is stated as desktop, mobile, WebGL and consoles, and the transports list is long: UDP, WebSockets, Steam, Unity Transport (UTP), Nakama, Local with no socket, PurrTransport, which is the project's own relay and is free for development and self-hostable for free if you would rather run it yourself, with optional direct WebRTC P2P, and Composite, which allows multiple transports at once. There is also an Edgegap addon for managed server deployment.

Where PurrNet is the wrong tool

The first limit is the maturity of the API you are building against. The recent releases are all 1.25.0 betas, with three of them in the last four days, and the repository's default branch is dev, described as more prone to breaking changes. A networking framework is a layer that everything in your game depends on, and a beta line means the API you integrate against is still moving.

The second is the compile-time post-processor. The convenience of Instantiate() being a networked spawn is bought with a build step that inspects your code, and that has consequences. It means the build is not just a build, and a team that has to support a headless build server or a custom CI pipeline has to make sure the post-processor runs there too. It also means that some of the behaviour you rely on is not visible in your source, which is a genuine cost when a developer is reading the code to understand what happens on the wire.

The third is that the network rules model, for all its flexibility, is a policy you have to design. The ability to let clients spawn and despawn their own objects is a feature only if your game's rules say so, and writing those rules is work that does not appear in any code sample.

The fourth is the transport list. Supporting Nakama, Steam, Edgegap and WebRTC P2P means the framework is wide, and a project that only needs UDP over a dedicated server is being offered a lot of surface. Each transport is a thing to configure, to test, and to reason about when something goes wrong.

The fifth is the switch cost. The migration guides are published for people coming from another solution, and the reason there is a guide is that the API is different in kind, not in name. If your project already has thousands of lines against another networking framework, the question is not whether PurrNet is nicer but whether rewriting the network layer is cheaper than living with the one you have.

Editorial conclusion

PurrNet is worth evaluating for a Unity team that finds the usual network object lifecycle noisy, because the entire premise is that spawning becomes an Instantiate call and RPCs become an attribute on a method, and because the network rules system moves authority from hard-coded checks into a per-object policy you can change without touching game code. It is the wrong choice if your project is already deep into another networking solution, since the migration guides exist precisely because this is a different abstraction. Before you commit, check the three things the project tells you: the Unity floor of 2022 or newer; that the release branch is the one to install and the dev branch is more up to date and more prone to breaking changes; and that the current release line is a 1.25 beta, so the API you build against today is still moving.

Frequently asked questions

How do I install PurrNet in a Unity project?

Install it through Unity's Package Manager with a Git URL pointing at the release branch, https://github.com/PurrNet/PurrNet.git?path=/Assets/PurrNet#release, or the dev branch for the more up to date and more breaking change prone line. It is also available through OpenUPM with openupm add dev.purrnet.purrnet and from the Asset Store, where versions lag behind. Unity 2022 or newer is required.

What are Network Rules in PurrNet?

They are a per-object policy for who may spawn, despawn, own, observe and call. The policy can be server-strict or client-convenient, and the documentation stresses that you can change which you use without changing game code, so that with permissive rules clients can even spawn and despawn their own objects.

Which kinds of RPC does PurrNet support?

There are TargetRPCs, ServerRPCs and ObserverRPCs, and depending on your network rules clients can call them directly too. The documentation shows static RPCs, awaitable RPCs returning Task, UniTask integration, coroutine RPCs and generic RPCs, and notes that these can be combined, for example a static RPC that returns a value and is awaitable and generic.

Official sources

  1. License: MIT
  2. Project website
  3. PurrNet/PurrNet on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/purrnet-purrnet.svg)](https://hysenlabs.com/projects/purrnet-purrnet)

Was this useful?