Mirror
  • Mirror Networking
  • API Reference
  • Development Blog
    • A Brief History of Mirror
  • User Manual
    • General
      • Getting Started
      • Script Templates
      • Change Log
        • 2024 Change Log
        • 2023 Change Log
        • 2022 Change Log
        • 2021 Change Log
        • 2020 Change Log
        • 2019 Change Log
      • Deprecations
      • Migration Guide
      • Integrations
      • Timestamp Batching
      • TCP and UDP
      • CCU
      • SyncDirection
      • Round Trip Time (RTT)
      • Connection Quality
      • Lag Compensation
      • Client Side Prediction
      • History Bounds
      • Tests
      • NetGraph
    • FAQ
      • Execution Order
    • Transports
      • KCP Transport
      • Telepathy Transport
      • WebSockets Transport
        • Reverse Proxy
          • Windows
            • IIS
          • Linux
            • NGINX
            • Caddy
            • Apache
            • HA Proxy
        • SSL
      • Multiplex Transport
      • Latency Simulation Transport
      • Ignorance
      • LiteNetLib Transport
      • FizzySteamworks Transport
      • FizzyFacepunch Transport
      • Encryption Transport
      • Edgegap Transports
        • Edgegap Relay
        • Edgegap Lobby
    • Components
      • Network Animator
      • Network Authenticators
        • Basic Authenticator
        • Device Authenticator
      • Network Behaviour
      • Network Discovery
      • Network Identity
      • Network Manager
      • Network Manager HUD
      • Network Ping Display
      • Network Profiler
      • Network Rigidbody
      • Network Lerp Rigidbody
      • Network Room Manager
      • Network Room Player
      • Network Start Position
      • Network Statistics
      • Remote Statistics
      • Network Transform
        • Snapshot Interpolation
      • Deprecated
        • Network Proximity Checker
        • Network Scene Checker
        • Network Match Checker
        • Network Owner Checker
    • Interest Management
      • Spatial Hashing
      • Distance
      • Scene
      • Scene + Distance
      • Match
      • Team
      • Custom
      • Legacy
    • Guides
      • Authority
      • IDs
      • Attributes
      • Time Synchronization
      • Data types
      • Serialization
      • Synchronization
        • SyncVars
        • SyncVar Hooks
        • SyncEvent (Obsolete)
        • SyncLists
        • SyncDictionary
        • SyncHashSet
        • SyncSortedSet
      • Communications
        • Remote Actions
        • NetworkManager Callbacks
        • NetworkBehaviour Callbacks
        • Network Messages
      • GameObjects
        • Player Game Objects
        • Custom Character Spawning
        • Custom Spawn Functions
        • Scene GameObjects
        • Pickups, Drops, and Child Objects
    • Examples
      • Additive Levels
      • Additive Scenes
      • Basic
      • Billiards
      • Multiple Additive Scenes
      • Pong
      • Room
      • Tanks
      • EdgegapLobby
  • Server Hosting
    • The Pragmatic Hosting Guide
    • Cloud Hosting Guides
      • AWS
      • Google Cloud
      • Oracle Free Tier
    • Hosting with a Remote Desktop
    • Edgegap Hosting Plugin Guide
  • Security
    • Security Overview
    • Cheat Protection Stages
    • Cheats & Anticheats
  • Community Guides
    • Community Translations
    • Video Tutorials
    • Resources
    • Mirror Quick Start Project
    • Unity for MMORPGs
    • Unity Canvas HUD
    • Odin Inspector Support
    • Ready Up And Die!
    • iOS AppStore
    • Mirror Docker Guide
    • Gitbook Guide
    • Mirror Branding
    • Contributors Agreement
    • Documentation License
Powered by GitBook
On this page
  • Batching
  • Timestamps
  1. User Manual
  2. General

Timestamp Batching

PreviousIntegrationsNextTCP and UDP

Last updated 3 years ago

Let's learn how Mirror sends around messages.

Batching

Every message that you send will be batched until the end of the frame in order to minimize bandwidth and transport calls. For example, if you send a lot of 10 byte messages then we can usually fit ~120 of them into one MTU sized batch of around 1200 bytes.

For the Transport, it's pretty convenient to send around messages in 1200 byte chunks (see ). Messages larger than MTU are sent as a single batch. To be exact, the Transport decides the batch siz that Mirror aims for via Transport.GetBatchThreshold().

Mirror batching is bidirectional. Which means that both the client and the server batch their messages and flush them out at the end of the frame.

In short, batching significantly reduces bandwidth and improves performance.

Timestamps

For some networking components, it's useful to know exactly when a message was sent by the remote.

For example, NetworkTransform receives the server's positions and then interpolates between them. For a smooth interpolation, we need to exactly reconstruct what happened on the server. For that, we need to know when an object has been at a certain position on the server.

The obvious solution is to simply send both timestamp and position every time:

[Rpc]
public void RpcPositionUpdate(float timestamp, Vector3 position)
{
    // ...
}

In fact, that's what an early version of our new NetworkTransform component did.

For the above code, we pay a significant bandwidth cost because for every position message, we also need to include a 4 byte float (or even better, an 8 byte double for higher precision). When synchronizing large worlds, the bandwidth would add up quickly.

NetworkTransform is only one of many components. Several others might need timestamps too, which would increase bandwidth even further.

To make life easier, Mirror includes an 8 byte double precision timestamp in every Batch. Instead of including it in every message, we include it once per ~1200 byte batch which is barely noticeable when it comes to bandwidth.

For any message handler in Mirror, you can get the timestamp from the batch it arrived with via NetworkConnection.remoteTimeStamp.

  • On the client, all object data arrives in messages/batches from the server. So at any given time, you can find out when an object's Rpc/OnDeserialize/OnMessage handler was sent by the server via NetworkClient.connection.remoteTimeStamp.

    • Note that on the client, we don't use an object's connectionToServer because only the player owned objects have connections to the server. Instead we use the client's NetworkClient.connection to server, which is always guaranteed to be there.

  • On the server, only player owned objects get messages from player connections. So at any given time, you can find otu when object's Cmd/OnDeserialize/OnMessage handler was sent by the client via connectionToClient.remoteTimeStamp.

Timestamp Batching is Mirror's unique approach to general purpose world synchronization. For example, Quake's Delta Snapshots are ideal for FPS games where the whole world fits into one world state message, while not being ideal for larger MMO sized worlds with lots of entities. Or perhaps you are working on a multiplayer text adventure with barely any world state, but still lots of network messages. Timestamp Batching fits well into Mirror's architecture. It should help you to reduce bandwidth no matter what type of project you work on.

MTU