This document describes the overall architecture of Normcore and how state is synchronized between players.
Rooms in Normcore are used to separate groups of players. They’re most commonly used to host a single match for a game, or a single persistent space for a productivity app. Players who join the same room name will be automatically connected to the same room.
You can create as many rooms as you’d like, and Normcore will automatically determine the ideal region to host the Room based on the players who are connecting.
Normcore also supports connecting to multiple rooms at once. This can be especially useful if you need to segment a large open world into multiple quadrants that players can freely move between.
All Room state is synchronized using a Datastore. If you need to move an object in the world, you change its position in the Datastore. The datastore will automatically detect any changes and notify all clients who are connected to the room so they can update their world to match.
Traditionally, application state is communicated between clients through events. Players send event messages like “Move Object A to (x, y, z)”. However, if a player joins the match late, one of the existing clients would now responsible for catching up the new client with the state of the room. It becomes pretty easy to spend most of your time trying to engineer ways to keep your clients in sync.
With Normcore’s datastore, there’s no need to manually synchronize clients like this. If you make a change to the datastore, it’s automatically replicated to all connected clients. And when a client joins a room late, the server is able to send them a complete copy of the datastore, without requiring any intervention from the other clients.
To conserve on bandwidth, once the server has sent the initial datastore snapshot, it will only send delta updates for the remainder of the session.
Model / View / Controller
Normcore uses an MVC (Model, View, Controller) based architecture, in order to help establish a clear separation of concerns for what handles your networking code.
The Datastore holds a collection of RealtimeModel objects, and ensures that they’re kept in sync between clients. In Unity, each GameObject represents the visual state of your app, so we consider it to be the View. And finally, the RealtimeComponents act as the controller.
A look at RealtimeTransform
Let’s dissect the RealtimeTransform component to get an understanding of how this works.
RealtimeTransform is a component that synchronizes the transform of a GameObject between clients.
Whenever a GameObject is moved, RealtimeTransform grabs the latest position / rotation / scale, and stores it in the datastore. That change is then replicated to all clients in the room, who can update the transform of their own copy of the GameObject.
That’s all for the Core Concepts section. If you’re ready to get your hands dirty, the rest of the guides from here on out walk through using Normcore in your own apps.
Check them out here: