# Mirage: a Unity networking library rebuilt on events and exceptions

> Mirage is a high-level networking library for Unity that replaces Mirror's global manager and override model with per-object events, strict exception-based error handling and a structured socket layer, and it adds the things a live service needs, server RPC return values, rate limiting, bit packing and error flags for misbehaving clients. It suits a team building an MMO, a co-op game or an FPS who want server authority enforced by construction rather than by convention, and it is a hard fork, so migrating means rewriting call sites rather than swapping a package.

**MirageNet/Mirage** — Easy to use high performance Network library for Unity 3d

- Repository: https://github.com/MirageNet/Mirage
- Website: https://miragenet.github.io/Mirage/
- Stars: 573 · Forks: 67
- Language: C#
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/miragenet-mirage

## Events instead of a global NetworkManager

Mirage is a high-level networking library for Unity. It is modular, performant, and designed to be easy to use, whether you are building an MMO, a co-op game, or an FPS. The project describes it as battle-tested in released games and built with security in mind, with many tools to help prevent multiplayer exploits. It is open source, and the README asks for bug reports and feedback either as GitHub issues or on the Discord.

The architectural decision that defines it is the shift from a central manager to per-object events. The quick look shows a GameSetup class holding a NetworkServer and a NetworkClient as public fields, and subscribing in Awake:

```csharp
public class GameSetup : MonoBehaviour
{
    public NetworkServer Server;
    public NetworkClient Client;

    private void Awake()
    {
        Server.Authenticated.AddListener(OnPlayerJoined);
        Server.Disconnected.AddListener(OnPlayerLeft);
        Client.Authenticated.AddListener(OnConnected);
    }

    private void OnPlayerJoined(INetworkPlayer player) { /* spawn logic */ }
    private void OnPlayerLeft(INetworkPlayer player) { /* cleanup logic */ }
    private void OnConnected(INetworkPlayer player) { /* client ready */ }
}
```

The comment on that block in the README says it plainly: Server and Client events, listen from anywhere, no central manager needed.

Compare that with the comparison table's row for Mirror, where events are described as override methods with a large `NetworkManager` class with single overrides. That is the whole difference in one line, and it propagates through the rest of the design. There is no static state, so multiple server and client instances can run in the same Unity process, which matters for a tool that also wants to work in an editor with two instances side by side. And the code style follows C# conventions rather than the older library's looser approach.

The `NetworkBehaviour` layer builds on that, carrying SyncVars, RPCs and Identity events, with the second example showing a combat class subscribing to `Identity.OnStartServer`.

The package is MIT licensed, published on OpenUPM as `com.miragenet.mirage`, with a GitHub Actions build and a release badge. The recent releases are v159.1.1 from 2026-10-15, v159.1.0 from 2026-10-11 and v159.0.0 from 2026-09-23, and the last push was on 2026-10-18.

## Rate limits, return values and error flags as attributes

The security story in Mirage is mostly in the attribute layer, and the same example class shows all three mechanisms at once.

```csharp
public class PlayerCombat : NetworkBehaviour
{
    [SyncVar]
    public int health = 100;

    private void Awake()
    {
        Identity.OnStartServer.AddListener(OnStartServer);
    }

    private void OnStartServer() { /* server-side init */ }

    [ServerRpc]
    // Rate limit to block spam
    [RateLimit(Refill = 1, MaxTokens = 5, Penalty = 10)]
    public void CmdAttack(NetworkIdentity target)
    {
        // validate and apply damage
    }

    [ServerRpc]
    [RateLimit(Refill = 1, MaxTokens = 5, Penalty = 50)]
    // return values so client can await result to know if they were successful or not
    public UniTask<bool> CmdBuyItem(int itemId)
    {
        if (!HasEnoughGold(itemId))
            return UniTask.FromResult(false);

        AddItemToInventory(itemId);
        return UniTask.FromResult(true);
    }
}
```

The `RateLimit` attribute is a token bucket with a refill rate, a maximum token count and a penalty. The first one, Refill 1, MaxTokens 5 and Penalty 10, allows a short burst of five attacks and then meters out one per unit of time, with a penalty applied for exceeding it. The comment in the source says rate limit to block spam, which is the point: the limit is declared next to the method it protects rather than being implemented in shared code that someone can forget to call.

The second example shows the return value feature. A ServerRpc can return a `UniTask<bool>`, so the client can await the result and know whether the call succeeded. The comment in the README says return values so client can await result to know if they were successful or not. The body returns false when the player lacks gold and true after the item is added, and the UniTask comes from UniTask, which the scoped registry list in the install instructions confirms is a dependency, `com.cysharp.unitask`.

The remaining features in the list follow the same philosophy. Max Length validation via attributes puts a size limit on an incoming message. Error Flags track misbehaving clients and what errors they are causing. Bit Packing optimises network messages and reduces bandwidth. Version Defines is about compile-time symbol selection, linked to the Unity manual for script compilation.

The strict error handling is the part that changes how you write code. The README's comparison table says errors are thrown as exceptions in Mirage, where Mirror logs them, and the feature list spells out the reason: invalid calls throw exceptions so bugs surface immediately instead of silently corrupting state. That is a good trade for a networked game, where a silently ignored RPC is a bug that only shows up as a desync hours later.

## Installing through OpenUPM, and what the Unity version requirement costs

The install path runs through the OpenUPM registry rather than the Unity Asset Store, which is the first difference from Mirror.

Mirage requires at least Unity 2022 LTS, and the README asks you to install Unity 2022 LTS via the Unity website or via the Unity Hub. You may use newer versions, however, LTS versions are strongly recommended as newer versions can contain bugs, glitches, or just flat-out break game projects. The recommendation is emphatic, and it is worth taking seriously given that the library is a fork with its own package identity.

The steps then run through the Package Manager. You start a new project or open an existing one, and if opening an existing one it is strongly recommended to back it up before installing Mirage. You add the OpenUPM registry through Edit, Project settings, then Package Manager, and the scoped registry is named OpenUPM with the URL `https://package.openupm.com` and the scopes `com.cysharp.unitask`, `com.openupm`, `com.miragenet` and `com.miragenet.mirage`.

Then you open the Package Manager from the Window menu, select Packages, My Registries, choose the latest version of Mirage and click install. And you can come back to the package manager at any time to uninstall Mirage or upgrade it.

If you would rather pin a specific version or hash, there is a Git URL alternative, added to the `dependencies` section of your `Packages/manifest.json`:

```json
"com.miragenet.mirage": "https://github.com/MirageNet/Mirage.git?path=/Assets/Mirage#v156.2.4",
```

That line shows the shape of the package, with the assets living under an `Assets/Mirage` path in the repository and the version pinned by a tag. It also shows the version scheme, because that example pins v156.2.4 while the current release is in the v159 line.

The backing documentation site is at miragenet.github.io/Mirage, and the migration path from Mirror is a separate guide, with the README recommending the Migration Guide for a smooth transition and noting there are some major differences between Mirage and the other network library.

## What a hard fork of Mirror actually means for a codebase

The comparison table is the most useful document in the repository, and it is worth reading as a list of decisions rather than as a feature list.

Mirage is a hard fork of Mirror, with many added features, performance improvements, and security improvements. Hard fork is the operative phrase. It means there is no compatibility layer between the two, so the migration is a rewrite of every call site, not a package swap.

The differences run across every axis. Installation moves from the Unity Asset Store to the Package Manager, through OpenUPM or a Git URL. Errors change from logged to thrown. The RPC attributes are renamed, with `[Command]` becoming `[ServerRpc]` and `[TargetRpc]` becoming `[ClientRpc(target = RpcTarget.Owner)]`, so every remote call in the project has to be found and updated. Messages no longer have to implement a NetworkMessage interface, since Mirage can send any data as messages, where Mirror constrained the payload. `NetworkTime` moves from a global static to something available on `NetworkBehaviour`. And the socket layer is described as structured with a consistent connection flow for all transports, where each transport in Mirror implemented its own connection logic.

The last point is the one that changes the architecture of the project rather than its syntax. A single connection flow across transports means the same code path works whether you are on a direct connection, a relay or something else, and the transport-specific code becomes a detail rather than a separate implementation you have to write and test per transport.

The remaining differences are mostly quality of life for the team. Network Behaviours can be on a root or a child GameObject, so you are not forced into a specific scene hierarchy for anything that needs to replicate. No static state means multiple instances in one process, which is how you test a client and a server locally.

For an existing Mirror project, the migration guide is the thing to read before anything else, because the practical question is how many call sites you have. The rename of the RPC attributes alone touches every remote call, and the change from logged errors to thrown ones means that code which previously ignored a failed call may now throw in a path that used to be quiet.

## The repository as a Unity package, and what the tooling says

The top level of the repository is laid out like a Unity project rather than like a plain C# library, which is the shape a package distributed through a package manager has to take.

There is an `Assets/` directory, which is where the Unity-visible parts of the package live, and a `Packages/` directory, and a `ProjectSettings/` directory, so the repository can be opened as a Unity project. There is a `doc/` directory holding the documentation that the site is built from, and the `Assets/Mirage` path referenced in the Git URL install is the same convention seen from the other side.

The tooling files show how the project is kept in shape. There are five `GlobalSuppressions.cs` files numbered one to five, which is what a large codebase accumulates when the static analyser has to be told where not to complain. A `.sonarlint/` directory points at SonarLint for editor integration, a `.editorconfig` and `.gitattributes` set the formatting rules, and a `commitlint.config.js` plus a `.releaserc.yml` show that the commit messages and the releases are both generated by tools rather than written by hand.

There is a `FUNDING.yml` and a `CONTRIBUTING.md`, and a `LICENSE` file, and the whole thing is MIT licensed, which matters for a library that other studios will embed in a commercial game.

The `ProjectsSettings` and `Packages` directories are the parts that make this unusual as a repository, and they are there so that the package can be opened, built and tested as a Unity project in CI without a separate harness project. For a user installing the package, none of that appears in their project, which is the point of the OpenUPM and Git URL routes. The install is a registry entry and a package manager click, and the two artefacts that matter to a consumer, the assembly and the dependencies, are resolved from the manifest.

## Conclusion

Adopt Mirage if you are building a Unity multiplayer game and want server authority, per-object events and request limits enforced by the framework, since the rate limiting and error flags are attributes rather than code you write each time. Do not adopt it as a drop-in swap for Mirror, because it is a hard fork with renamed attributes and different error semantics, and check first that your project can move to Unity 2022 LTS or newer, since that is the stated minimum and the recommendation is emphatic about staying on an LTS release.

## FAQ

### What is Mirage?

It is a high-level networking library for Unity, modular and performant, aimed at MMO, co-op and FPS projects. The project describes it as battle-tested in released games and built with security in mind, with many tools to help prevent multiplayer exploits, and it is MIT licensed and open source.

### How is Mirage different from Mirror?

Mirage is a hard fork of Mirror with added features and improvements. Errors are thrown as exceptions rather than logged, events are subscribed per object with no central manager, RPC attributes are renamed, any data can be sent as a message, and the socket layer has a consistent connection flow across all transports.

### How do I install Mirage in a Unity project?

Add the OpenUPM scoped registry with the URL https://package.openupm.com and the scopes com.cysharp.unitask, com.openupm, com.miragenet and com.miragenet.mirage, then install the package from the Package Manager under My Registries. You can also pin a version by adding a Git URL to the dependencies section of Packages/manifest.json.

### What security features does Mirage provide?

Rate limiting via a RateLimit attribute with a refill rate, maximum tokens and a penalty, Max Length validation on incoming messages, error flags for tracking misbehaving clients and the errors they cause, server RPCs that return values so a client can await the result, and bit packing to reduce bandwidth.

### Which Unity version does Mirage need?

At least Unity 2022 LTS. Newer versions may be used, but LTS versions are strongly recommended because newer ones can contain bugs, glitches or break game projects, and the README also strongly recommends backing up an existing project before installing.

### Is Mirage still being developed?

The repository is not archived and the last push was on 2026-10-18. Recent releases are v159.1.1 from 2026-10-15, v159.1.0 from 2026-10-11 and v159.0.0 from 2026-09-23, and the package is published on OpenUPM as com.miragenet.mirage.

## Sources

- [License: MIT](https://github.com/MirageNet/Mirage/blob/main/LICENSE)
- [MirageNet/Mirage on GitHub](https://github.com/MirageNet/Mirage)
- [Project website](https://miragenet.github.io/Mirage/)
- [README](https://github.com/MirageNet/Mirage/blob/main/README.md)
- [Releases](https://github.com/MirageNet/Mirage/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/miragenet-mirage
