LogoLogo
HomeOnline DashboardAPIDiscordForums
SDK 1.7 Preview
SDK 1.7 Preview
  • Welcome
  • Overview
    • Features
    • Roadmap
  • Getting started
    • Get the Unity SDK
    • Setup a project
      • 1. Scene setup
      • 2. Prefab setup
      • 3. Test your game locally
        • Local testing using builds
        • Local testing via Unity's Multiplayer Play Mode
        • Local testing via ParrelSync
      • 4. Test in the cloud
        • Deploy a Replication Server
        • Share builds
    • How to... ?
    • Single-player to multiplayer
    • Video tutorials
    • Samples and tutorials
      • Package samples
      • Sample Connection UIs
      • First Steps tutorial
        • 1. Basic syncing
          • 1.1 Animation parameters
          • 1.2 Sending commands
        • 2. Physics / Authority transfer
        • 3. Areas of interest
        • 4. Parenting entities
        • 5. Complex hierarchies
        • 6. Persistence
      • Campfire project
        • Game mechanics
        • Leveraging object pooling
        • Remote interactions: Chairs
        • Remote interactions: Trees
        • A unique object with complex state
        • Custom instantiation and destruction
        • Running a server-side NPC
        • Playing audio and particles
        • A simple text chat
      • Beginner's guide to networking
    • Troubleshooting
  • Manual
    • Unity Components
      • CoherenceSync
      • CoherenceBridge
      • CoherenceLiveQuery
      • CoherenceTagQuery
      • CoherenceGlobalQuery
      • CoherenceInput
      • CoherenceNode
      • PrefabSyncGroup
      • Order of execution
    • Networking state changes
      • Instantiate and Destroy Objects
      • Supported types
      • Messaging with Commands
      • Syncing child GameObjects
      • Animation
      • CoherenceSync references
      • [Sync] and [Command] Attributes
      • [OnValueSynced] Attribute
      • Creating your own syncable member
      • Custom Component Actions
      • Rigid Bodies
      • Interpolation
    • Authority
      • Authority transfer
      • Server-authoritative setup
    • Lifetime
      • Persistence
      • Uniqueness
      • Example: A global counter
    • Parenting network entities
      • Direct children CoherenceSyncs
      • Deeply-nested CoherenceSyncs
      • Nesting Prefabs at Edit time
    • Asset management
      • Instantiating from CoherenceSyncConfig
      • Instantiate via
      • Load via
    • Scene management
    • Multiple Connections within a Game Instance
    • Baking (code generation)
      • Conditional compilation
    • Replication Server
      • Rooms and Worlds
      • Replication Server API
    • Simulators (Servers)
      • Scripting: Client vs Simulator
      • Run local Simulators
      • World Simulators
      • Room Simulators
      • Advanced Simulator Authority
      • Simulator slugs
      • Build and Deploy
      • Command-line arguments
    • Client Connections
    • Optimization
      • Areas of Interest
      • Level of Detail (LOD)
      • Profiling
      • Simulation Frequency
    • Project Settings
    • Advanced topics
      • Big worlds
        • World Origin Shifting
        • Load balancing
      • Competitive games
        • Simulation Frame
        • Determinism, Prediction and Rollback
      • Team workflows
        • Version Control integration
        • Continuous Integration
      • Schema explained
        • Specification
        • Field settings
        • Archetypes
      • Code stripping
      • Replication Server CLI
      • Single-player gameplay
    • Scripting API
  • Hosting
    • Choosing where to host
    • coherence Cloud
      • Online Dashboard
      • Manage Worlds
      • Configure Rooms
      • Player Accounts
      • Game Services
        • Lobbies
        • Cloud Storage
        • Key-Value Store (Legacy)
      • APIs
        • Worlds
        • Rooms
        • Lobbies
        • Cloud Storage
        • Key-Value Store (Legacy)
    • Peer-to-peer
      • Implementing Client hosting
        • Steam Relay
        • Epic Online Services (EOS) Relay
        • Azure PlayFab Relay
  • Support
    • Release notes
    • Glossary
    • Unreal Engine support
    • WebGL support
    • ECS / DOTS support
    • Known issues
    • Upgrade guide
      • Upgrade 1.6 -> 1.7
      • Upgrade 1.5 -> 1.6
      • Upgrade 1.4 -> 1.5
      • Upgrade 1.3 -> 1.4
      • Upgrade 1.2 -> 1.3
      • Upgrade 1.1 -> 1.2
      • Upgrade 1.0 -> 1.1
      • Upgrade 0.10 -> 1.0
      • Upgrade 0.9 -> 0.10
    • Credit cost & pricing
    • Report a bug
Powered by GitBook
On this page
  • Fundamentals of networking
  • Synchronizing state
  • Common optimizations
  • The role of a central server
  • Authority
  • Error correction
  • Time and latency
  • Conclusions

Was this helpful?

Export as PDF
  1. Getting started
  2. Samples and tutorials

Beginner's guide to networking

Erik Svedäng, the winner of IGF 2009, explains the high-level concepts behind networking games.

Was this helpful?

Fundamentals of networking

This article will try to explain a handful of fundamental concepts that all are central to how networked games work. It does not contain any code examples and tries to not delve into minor details. Instead, its goal is to prepare someone new to the field for thinking about networking from a high-level perspective; what problems can arise and how they are commonly solved. The information in here is very useful for understanding the coherence SDK, but it should also be general enough to be applicable to any other similar networking library.

Synchronizing state

When a game runs on your local computer, it contains a lot of which is used to model the game. This includes things like animation state, the position and orientation of various game objects, AI calculations, physical forces, among with any gameplay-specific variables. Colloquially we refer to all of this data as state. Efficiently updating state is a hard problem, even for a game that is only running locally.

To create the illusion that you're playing together in the same game world, a networked multiplayer game has to transmit enough of its state to the other players. Since computer networks have limited it is absolutely necessary to restrict the amount of data being sent.

Generally speaking, there are two main ways to synchronize state; we can either send inputs, or the updated data itself. It is also possible to mix these approaches in various ways. We will now discuss each of the options briefly.

1. Sending inputs

It is usually possible to enumerate a number of predefined inputs that the players of the game are allowed to perform (e.g. "jump", "run", "activate"). When an input is applied to the local game state, we can also make sure it is simultaneously sent to every other player in the session. If we make sure that each player starts the game in exactly the same state, and make sure that everyone applies exactly the same inputs as everyone else, the game state will appear in sync for each player. For certain types of games, this can save a lot of data from having to be transferred.

A good example might be an game with hundreds of units, where it might be enough to send the coordinates of mouse clicks instead of the location of each unit. This of course requires completely deterministic game logic, which is a challenge in itself.

Another problem is that if there's even the slightest mismatch in inputs, the local game states of the players will begin to diverge. To learn more about this approach (and how to work around some of the problems) see our documentation on .

It is noteworthy that sending inputs doesn't necessarily require a server; thus it is a great model to be used in a peer-to-peer setting.

2. Sending updates

A second approach is to send the updated data itself. This can often be more costly in terms if data transfer (a single player action can change a lot of local data, which in turn has to be transmitted to the other players). It leads to some nice benefits though; most importantly that game states are allowed to diverge slightly, as long as they have a chance to catch up.

Since it's the clients that run the simulation locally and then send the updated game state to the server, this setup can be referred to as client-authoritative.

3. Inputs + updates

It is also worth noting that you can combine client-authoritative simulation with inputs in interesting and useful ways. For example, it is possible to let players simulate some less-critical parts of the game state locally, while still sending inputs for their characters to a central server to be processed.

Common optimizations

As stated before, a game contains a lot of data and it is not feasible to send all of it over the network in a real-time fashion. While using inputs is often the most lightweight choice in terms of data usage, it is common to have to send updates to the game state - both from the client to the server, and vice versa. In both those cases we have to use some optimizations. Here are the most important ones.

By keeping track of what the other players know about the state of your game, it is often possible to avoid a lot of data transfer. For example, a player might drop some game object on the ground and send the new location of it to each other participant. Unless that object moves, it is unnecessary to keep sending the same position over and over. This simple idea is used pervasively in coherence (and other similar networking solutions) to great effect.

It's important to acknowledge that a game sometimes generates many changes in a short timeframe. In such a situation, it is useful to prioritize changes based on how important they are for the particular game in question, while also factoring in how long it has been on hold. This means that an "old" change that doesn't get sent will build up importance and relative priority compared to other changes, eventually getting sent.

The role of a central server

This modular approach where various tasks are performed by different programs, potentially on different machines or from different physical locations, can help with the scaling of a game if it has many users.

Authority

Most people who play computer games versus other people online want it to be fair, with equal conditions for each player.

If your game is client-authoritative, with clients sending updates of the game state to the server, we can't verify the validity of such an update and it becomes a problem. It would be quite feasible for a savvy player to modify their game and remove certain limitations put there by the game developer.

As an example, a game client could send an update that sets the health of each enemy to 0. To prevent such blatant cheating, it is useful to introduce the concept of authority (also often called "ownership"). This means that the Replication Server keeps track of which client has the rights to update each entity in the game. If an unauthorized update is sent to the server, it is rejected and will not get sent to any other participant.

For an input-based game, the cheating problem is slightly different. Since inputs will have to be applied in the right situation to have any effect, it is much harder to simply set the game state to illegal values. The role of authority in this case is to make sure that no player sends inputs for a game object they shouldn't be able to control.

Error correction

This design does not work well for fast-paced games, since their simulations run at many frames per second. By the time a lost network message has been resent and finally made it to its final address, the information in it will have a high chance of already being outdated.

Time and latency

Sending data from one computer to another takes time, and there's no way around that. As a programmer of a networked game, it is important to embrace this fact and recognize that it changes how you must think about your game logic. When programming a single-player game (especially if it only runs on a single processor thread) we can assume that any change to the game state is immediate. In a networked game, this is not true.

This means that each player of a networked game is playing in their own "parallel universe", which affect each other at a distance. Updates to data that you don't have authority over will appear in an irregular and unpredictable way. Because of this it is beneficial to use a defensive coding style that tries to correct for out-of-order updates, and other unexpected circumstances.

Conclusions

This concept is usually referred to as . Not having a single "initial state" also makes it easier to support features like letting players join late, or backing up the state of the game world.

A third option is a combination of the two solutions above, where clients send inputs but receive updated world data. This requires a central that is be able to run the game logic. The Simulator is a program trusted by the game developer and it knows how the inputs sent by the players are supposed to affect the game state.

This is a server-authoritative setup; players won't be in charge of the simulation and can't affect the game state directly. This has multiple implications, for example it shifts some of the burden of computation from user devices onto the server. To read more about this approach, see .

Finally, a major way of limiting data usage is to filter out uninteresting information and only send the most important parts based on the needs of each participant, also known as . Most commonly this takes the form of a position-based query. The query will make sure that a specific player only gets updates from objects in its vicinity. Anything far away will simply be ignored, and no data has to be sent. It is also possible to send some (but less detailed) data depending on distance. To learn more about these techniques, take a look at the coherence documentation for and .

A game can have many users, and to facilitate the optimizations mentioned in the previous section it is necessary to track what each participant knows about the game state (and what they are interested in knowing). Instead of putting this burden on each game client, which entails an additional performance cost and can be hard to coordinate, it is better to make this part of a central server. For coherence, this is named the .

In the case of using an input-based setup, there also has to be a central arbiter in charge of handling the received inputs, applying them to the game state, and sending the new game state to each client. In a coherence setup, the simulation of the game (which requires game-specific knowledge) is handled by a which communicates with the Replication Server.

In many cases it is useful to allow for the . For example, there could be a magical potion that you can drink from in the game. If a player has authority over the potion, she can move it around and drink from it, or refill it. If she then gives the potion to another player, they would get authority over it and the original player would no longer be able to update it.

For certain game objects where we don't trust the players with updating them (or don't want potentially expensive logic to run on their devices) it is also possible to have dedicated machines that have authority over those objects and update them (see ).

There are multiple ways of sending data over a network. These are called protocols. When speed is not the single most important factor, is often used. It has mechanisms for checking that the correct information was sent and it will try to resend the information if it was lost along the way to it recipient.

So instead of TCP, games often use . This protocol is unreliable by design, but coherence adds a reliability layer on top of it. If turns out that an update didn't make it to its recipient, that update will be re-sent, but only after checking if any more recent changes to its data exist. This way, it is more likely that each player gets a consistent and up-to-date view of the shared game state.

One example of such a coding technique (which is already built into coherence) is . It uses a selection of algorithms to predict what a value will be, based on previous values. This "smooths out" the values over time, which often looks better than using the raw versions. The best example of this is probably interpolation of position - if an object is moving in a straight line at a certain speed and then the update with its new position is somehow lost, it is better to assume that the object will keep moving instead of stopping it.

If the concepts in this article were new to you, we hope that you now feel more confident thinking about the challenges of networked game. While networking surely can be tricky at times, it's also immensely cool and fun when it works - hopefully coherence will make you reach that point in no time! Our docs contain lots of information on how to proceed from here. Perhaps you should start by following a ?

data
bandwidth
RTS
GGPO
eventual consistency
Simulator
Server-authoritative setup
Area of Interest
Queries
Level of Detail
Replication Server
Simulator
transfer of authority
Simulators
TCP
UDP
interpolation
tutorial