# Table of Contents - [A Brief History of Mirror | Mirror](#a-brief-history-of-mirror-mirror) - [Mirror Networking | Mirror](#mirror-networking-mirror) - [General | Mirror](#general-mirror) - [Getting Started | Mirror](#getting-started-mirror) - [Script Templates | Mirror](#script-templates-mirror) - [2025 Change Log | Mirror](#2025-change-log-mirror) - [Change Log | Mirror](#change-log-mirror) - [Execution Order | Mirror](#execution-order-mirror) - [2024 Change Log | Mirror](#2024-change-log-mirror) - [2023 Change Log | Mirror](#2023-change-log-mirror) - [CCU | Mirror](#ccu-mirror) - [KCP Transport | Mirror](#kcp-transport-mirror) - [Telepathy Transport | Mirror](#telepathy-transport-mirror) - [Integrations | Mirror](#integrations-mirror) - [2022 Change Log | Mirror](#2022-change-log-mirror) - [Timestamp Batching | Mirror](#timestamp-batching-mirror) - [Latency Simulation Transport | Mirror](#latency-simulation-transport-mirror) - [Migration Guide | Mirror](#migration-guide-mirror) - [History Bounds | Mirror](#history-bounds-mirror) - [SyncDirection | Mirror](#syncdirection-mirror) - [Reverse Proxy | Mirror](#reverse-proxy-mirror) - [Edgegap Transports | Mirror](#edgegap-transports-mirror) - [Edgegap Relay | Mirror](#edgegap-relay-mirror) - [NetGraph | Mirror](#netgraph-mirror) - [Multiplex Transport | Mirror](#multiplex-transport-mirror) - [FizzySteamworks Transport | Mirror](#fizzysteamworks-transport-mirror) - [Tests | Mirror](#tests-mirror) - [WebSockets Transport | Mirror](#websockets-transport-mirror) - [Round Trip Time (RTT) | Mirror](#round-trip-time-rtt-mirror) - [FizzyFacepunch Transport | Mirror](#fizzyfacepunch-transport-mirror) - [Connection Quality | Mirror](#connection-quality-mirror) - [2021 Change Log | Mirror](#2021-change-log-mirror) - [LiteNetLib Transport | Mirror](#litenetlib-transport-mirror) - [TCP and UDP | Mirror](#tcp-and-udp-mirror) - [Encryption Transport | Mirror](#encryption-transport-mirror) - [Transports | Mirror](#transports-mirror) - [Ignorance | Mirror](#ignorance-mirror) - [FAQ | Mirror](#faq-mirror) - [Lag Compensation | Mirror](#lag-compensation-mirror) - [iOS AppStore | Mirror](#ios-appstore-mirror) - [Resources | Mirror](#resources-mirror) - [Odin Inspector Support | Mirror](#odin-inspector-support-mirror) - [Mirror Branding | Mirror](#mirror-branding-mirror) - [Mirror Docker Guide | Mirror](#mirror-docker-guide-mirror) - [Unity for MMORPGs | Mirror](#unity-for-mmorpgs-mirror) - [SSL | Mirror](#ssl-mirror) - [Video Tutorials | Mirror](#video-tutorials-mirror) - [Scene + Distance | Mirror](#scene-distance-mirror) - [Contributors Agreement | Mirror](#contributors-agreement-mirror) - [Documentation License | Mirror](#documentation-license-mirror) - [Community Translations | Mirror](#community-translations-mirror) - [Cheat Protection Stages | Mirror](#cheat-protection-stages-mirror) - [Spatial Hashing | Mirror](#spatial-hashing-mirror) - [Match | Mirror](#match-mirror) - [Security Overview | Mirror](#security-overview-mirror) - [Components | Mirror](#components-mirror) - [Hex Spatial Hashing | Mirror](#hex-spatial-hashing-mirror) - [Cloud Hosting Guides | Mirror](#cloud-hosting-guides-mirror) - [IDs | Mirror](#ids-mirror) - [Distance | Mirror](#distance-mirror) - [Time Synchronization | Mirror](#time-synchronization-mirror) - [Scene | Mirror](#scene-mirror) - [Gitbook Guide | Mirror](#gitbook-guide-mirror) - [Team | Mirror](#team-mirror) - [Guides | Mirror](#guides-mirror) - [Interest Management | Mirror](#interest-management-mirror) - [The Pragmatic Hosting Guide | Mirror](#the-pragmatic-hosting-guide-mirror) - [2019 Change Log | Mirror](#2019-change-log-mirror) - [Network Profiler | Mirror](#network-profiler-mirror) - [Additive Scenes | Mirror](#additive-scenes-mirror) - [Tanks | Mirror](#tanks-mirror) - [Authority | Mirror](#authority-mirror) - [Additive Levels | Mirror](#additive-levels-mirror) - [Network Animator | Mirror](#network-animator-mirror) - [Network Ping Display | Mirror](#network-ping-display-mirror) - [Network Rigidbody | Mirror](#network-rigidbody-mirror) - [Multiple Additive Scenes | Mirror](#multiple-additive-scenes-mirror) - [Oracle Free Tier | Mirror](#oracle-free-tier-mirror) - [Billiards | Mirror](#billiards-mirror) - [Device Authenticator | Mirror](#device-authenticator-mirror) - [Network Lerp Rigidbody | Mirror](#network-lerp-rigidbody-mirror) - [Client Side Prediction | Mirror](#client-side-prediction-mirror) - [Attributes | Mirror](#attributes-mirror) - [Hosting with a Remote Desktop | Mirror](#hosting-with-a-remote-desktop-mirror) - [Unity Canvas HUD | Mirror](#unity-canvas-hud-mirror) - [Ready Up And Die! | Mirror](#ready-up-and-die-mirror) - [Basic Authenticator | Mirror](#basic-authenticator-mirror) - [2020 Change Log | Mirror](#2020-change-log-mirror) - [Network Start Position | Mirror](#network-start-position-mirror) - [Remote Statistics | Mirror](#remote-statistics-mirror) - [Network Statistics | Mirror](#network-statistics-mirror) - [Legacy | Mirror](#legacy-mirror) - [Basic | Mirror](#basic-mirror) - [Pong | Mirror](#pong-mirror) - [Network Room Player | Mirror](#network-room-player-mirror) - [Network Manager HUD | Mirror](#network-manager-hud-mirror) - [Network Identity | Mirror](#network-identity-mirror) - [Edgegap’s Dedicated Game Server Hosting – Plugin Guide | Mirror](#edgegap-s-dedicated-game-server-hosting-plugin-guide-mirror) - [Cheats & Anticheats | Mirror](#cheats-anticheats-mirror) - [Communications | Mirror](#communications-mirror) - [Custom | Mirror](#custom-mirror) - [Examples | Mirror](#examples-mirror) - [Room | Mirror](#room-mirror) - [AWS | Mirror](#aws-mirror) - [Scene GameObjects | Mirror](#scene-gameobjects-mirror) - [Network Manager | Mirror](#network-manager-mirror) - [Network Transform | Mirror](#network-transform-mirror) - [GameObjects | Mirror](#gameobjects-mirror) - [Network Room Manager | Mirror](#network-room-manager-mirror) - [Player Game Objects | Mirror](#player-game-objects-mirror) - [NetworkManager Callbacks | Mirror](#networkmanager-callbacks-mirror) - [Network Discovery | Mirror](#network-discovery-mirror) - [Serialization | Mirror](#serialization-mirror) - [SyncEvent (Obsolete) | Mirror](#syncevent-obsolete-mirror) - [Network Messages | Mirror](#network-messages-mirror) - [Google Cloud | Mirror](#google-cloud-mirror) - [SyncVars | Mirror](#syncvars-mirror) - [NetworkBehaviour Callbacks | Mirror](#networkbehaviour-callbacks-mirror) - [Data types | Mirror](#data-types-mirror) - [Deprecated | Mirror](#deprecated-mirror) - [SyncVar Hooks | Mirror](#syncvar-hooks-mirror) - [Network Owner Checker | Mirror](#network-owner-checker-mirror) - [Remote Actions | Mirror](#remote-actions-mirror) - [Network Proximity Checker | Mirror](#network-proximity-checker-mirror) - [Snapshot Interpolation | Mirror](#snapshot-interpolation-mirror) - [Network Authenticators | Mirror](#network-authenticators-mirror) - [Network Match Checker | Mirror](#network-match-checker-mirror) - [Custom Character Spawning | Mirror](#custom-character-spawning-mirror) - [Network Scene Checker | Mirror](#network-scene-checker-mirror) - [SyncSortedSet | Mirror](#syncsortedset-mirror) - [SyncHashSet | Mirror](#synchashset-mirror) - [Custom Spawn Functions | Mirror](#custom-spawn-functions-mirror) - [Network Behaviour | Mirror](#network-behaviour-mirror) - [Synchronization | Mirror](#synchronization-mirror) - [SyncLists | Mirror](#synclists-mirror) - [Pickups, Drops, and Child Objects | Mirror](#pickups-drops-and-child-objects-mirror) - [Deprecations | Mirror](#deprecations-mirror) - [Mirror Quick Start Project | Mirror](#mirror-quick-start-project-mirror) - [SyncDictionary | Mirror](#syncdictionary-mirror) --- # A Brief History of Mirror | Mirror Our community has grown a lot. Most of you weren't around when this all started, so here's a brief history of UNET/Mirror. Hopefully an entertaining read if you are new to Mirror. Perhaps a trip down memory lane with some nostalgia screenshots for those who've been around all this time. circle-info We will keep updating this article as Mirror develops over time. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#unet) UNET ---------------------------------------------------------------------------------------------- ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXH9lMjdWhHuhBcBN_E%252F-MXHAYFxmfCl5YI2M08Y%252Fimage.png%3Falt%3Dmedia%26token%3Dd53954ee-d4b8-4c52-8952-53e158d5295a&width=768&dpr=3&quality=100&sign=7e9b00d7&sv=2) Back in summer 2015 Unity released a public beta of **UNET**. The idea of Unity worrying about networking so we could worry about our games sounded very tempting. UNET came with several interesting features: * **Server & Client in one project**. Most of the code is shared. Some is marked as \[Server\] or \[Client\] only. * This allows for a major gain productivity since terrain, models, assets and code are all shared between server & client. * **\[SyncVars\]** for automated serialization of selected variables. * This was significant when coming from hand built Serialize/Deserialize functions. Simply adding a \[SyncVar\] in front of Player. level was so much easier. * **\[Commands/Rpcs\]** - wrapping a function with a \[Command\] tag to automatically call it on the server was another huge gain productivity * Compared to manually sending a message, deserializing all parameters and calling a function manually. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#hype) Hype ---------------------------------------------------------------------------------------------- Back in 2015, there seemed to be almost monthly UNET talks and videos like [Democratizing Multiplayer Developmentarrow-up-right](https://www.youtube.com/watch?v=gZbbYXzyXKk) . Everyone was excited, and the UNET team was working hard. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXH8_xP0PhIX5eLVi-p%252F-MXH8xR0Fm7wCliTkm5B%252F2021-04-02_18-35-53%25402x.png%3Falt%3Dmedia%26token%3Daa64427f-e300-42e2-bcc9-d54efeff6c43&width=768&dpr=3&quality=100&sign=c9eafe63&sv=2) Sean Riley demonstrating UNET at Unite 2014 ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXFrPN6dXLtq8BDcAEK%252F-MXFrd9Qe6q1YuK8TJ47%252F2021-04-02_12-36-24%25402x.png%3Falt%3Dmedia%26token%3D922632e7-1496-444d-bb51-59d2c7fcad76&width=768&dpr=3&quality=100&sign=7be4976b&sv=2) One of the early UNET talks in 2015 ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXHA_7E9f5lLWQvbxNp%252F-MXHB7E4KB7AMJ5jqoAK%252F2021-04-02_18-45-38%25402x.png%3Falt%3Dmedia%26token%3D0d8655ea-92a7-4997-8fcf-8bd711c58500&width=768&dpr=3&quality=100&sign=630cf4cd&sv=2) Alexey Abramychev's talk about LLAPI Back then, it was mostly: * **Alexey Abramychev**: the friendly Russian guy who worked on the low level Transport (LLAPI) * **Sean Riley**: who worked on World of Warcraft, now developing the high level API (HLAPI/UNET) * **Erik Juhl:** the UNET team lead, who said _MMOs were his passion_ The UNET team had a big plans on their **roadmap**: * Cloud services like Relay/Matchmaking * One-click game server hosting right from the Unity Editor * The _simulation server_ which will power MMO scale networking * UNET 'Phase 3' aka automated server instances. Mark an area, it'll run as an instance. Most multiplayer games never see the light of day, because finishing all that code is extremely difficult. With UNET, for the first time it seemed actually doable. An order of magnitude gain productivity for sure. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#getting-started) Getting Started -------------------------------------------------------------------------------------------------------------------- UNET was still in beta in 2015. There wasn't much documentation, but there were just a couple of demos. One of them was a movement demo with a couple of balls moving over the network. I was already working on my MMO project before UNET. Moving balls sounded close enough to moving players, so I gave UNET a try. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXFna1_AS7mqjRnkQx-%252F-MXFo7glzUOkFpI8iCYD%252F2015-09-30_unet_noicons.png%3Falt%3Dmedia%26token%3Dc8ea6f90-492b-4608-8869-4b5026bca7cc&width=768&dpr=3&quality=100&sign=efff2645&sv=2) UNET's movement demo with some early MMO features **Networked** NavMeshAgent movement, skills, equipment and an inventory were added easily thanks to SyncLists and all the \[SyncVar\]/\[Rpc\] convenience. UNET wasn't very stable during the beta, but the productivity gain was massive and it seemed like the obvious path into the future of multiplayer game development. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#meet-damon) Meet Damon ---------------------------------------------------------------------------------------------------------- Around September I also started talking to Damon Slye, the guy who made [Red Baronarrow-up-right](https://store.steampowered.com/app/263940/Red_Baron_Pack/) in 1990, published by Sierra. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXFu3Kx1yqybXimM9XO%252F-MXFvIw2OsW364YUZCl4%252Fimage.png%3Falt%3Dmedia%26token%3D7360275c-1da4-4a11-9631-842533f538b7&width=768&dpr=3&quality=100&sign=beba0774&sv=2) Red Baron Damon and his new team Mad Otter Games actually made their own indie MMO, just like I planned to do. They didn't use Unity, but considered it for their next project. We've talked a lot about MMO tech, lessons learned and they even licensed me a couple of their models for my unnamed MMO project. With the UNET team working tirelessly on networking and the MadOtter guys as living proof, it seemed like my indie MMO idea actually seemed almost doable for once. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#what-if) What if... ------------------------------------------------------------------------------------------------------- ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXFwlgK4N7jdJ0d8_dN%252F-MXFx-cuF7YTuNnTDNN_%252F2021-04-02_13-00-01%25402x.png%3Falt%3Dmedia%26token%3D03acc7e9-6069-4b89-b6a2-284b90b2b592&width=768&dpr=3&quality=100&sign=e226e546&sv=2) The MMO Project in November 2015 with the licensed models. In 2015, there wasn't any type of MMO toolkit available as far as I could tell. From my reverse engineering days I remembered Perfect World Entertainment licensing their MMO engine for $100,000 - $300,000. Which needless to say was out of my budget. Since I was working on my own MMO code anyway, I figured might as well put it on the Asset Store and see what happens. Maybe it sells for $50/month and I can treat myself to a pizza every week or so. [uMMORPGarrow-up-right](https://assetstore.unity.com/packages/templates/systems/ummorpg-remastered-159401) was released on the Asset Store at December 23rd, 2015. One day before Christmas. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXGf9ZGdg46Xl8gXTMJ%252F-MXGgOA8YSgPPCXusW42%252F2017-01-11_10-42-44.png%3Falt%3Dmedia%26token%3De535705d-6259-4a48-9808-bca549d3d772&width=768&dpr=3&quality=100&sign=659325ee&sv=2) An early version of uMMORPG As it turns out, a lot of people had the same dream, but not enough money to license a AAA engine. uMMORPG quickly became one of the top 10 assets on the store. Yesterday, MMO development was my hobby, a dream to work on my free time. Over night it became a full time job, thanks to the Unity Engine, UNET and a huge bet. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#in-unet-we-trust) In UNET We Trust ---------------------------------------------------------------------------------------------------------------------- Around that time, **Paul** and I crossed paths when he used uMMORPG for his Cubica game. There was just one problem: UNET. We've put all our trust into a networking black box and a couple of professional networking engineers. Yet, even after 30-50 bug reports and 1-2 years of begging every single person on the UNET team - nothing happened. Not a single bug was fixed. No improvements. No answers. Every single day our users/customers came in with new UNET bugs. Bad reviews. Random crashes. We've built our dreams on a blackbox that abandoned us, and there was nothing we could do about it. Worst of all, UNET didn't scale. 30-70 CCU and a dozen monsters were all it could do. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXGf9ZGdg46Xl8gXTMJ%252F-MXGiCqFBOdM1wG8pPAv%252F57.png%3Falt%3Dmedia%26token%3Ddb6ae66f-8d30-4762-bf1f-45156e32acf1&width=768&dpr=3&quality=100&sign=cde8c9c6&sv=2) An early UNET community test with 57 connections and lots of bugs. At one point, I used reflection to fix the serialization bug in UNET. At the time, it was the highest rated networking bug on the Unity issue tracker. I've made detailed forum posts on why the bug happens and how to fix it. I reached out to Alexey, Erik, Larus, the Asset Store team, and QA. It was closed _by design_. Twice. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXH920wUYsugoStSbPc%252F-MXH9fBNORwRSCC5Oeo2%252F2021-04-02_18-39-23%25402x.png%3Falt%3Dmedia%26token%3Da86883cf-0d9d-45dc-a0ff-b30febb9bda4&width=768&dpr=3&quality=100&sign=923ce6d6&sv=2) "By Design" - the UNET Bug that started Mirror We've built our dreams on UNET, and in my case my livelihood. I needed UNET to pay the rent and eat. Yet the people we've put our full trust in had abandoned us. * **Sean Riley** was the driving force behind UNET. As it turns out, he left the team around the beta. * **Alexey** tried to fill the void as best as he could. For a while, he was on the forum on Sundays and even replied to my email during his vacation. At some point, he wasn't with Unity anymore either though. * **Erik Juhl** (the UNET team lead) went on to work for a web development company. What's worse is that while everyone secretly left the sinking ship, there was no word from Unity. Dead silence. It took a couple of years for us to learn that the UNET core team wasn't even working for Unity anymore. At one point we even wrote an open letter to Joachim Ante. Desperate times. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#hlapi-pro) HLAPI Pro -------------------------------------------------------------------------------------------------------- In a surprising turn of events, someone at Unity **open sourced HLAPI** - the high level part of UNET. **LLAPI** - the low level transport - always remained closed source. For HLAPI, one had to compile two csharp DLLs, manually overwrite them in their Unity installation and then pray that it was compatible with that particular Unity version. The code was uncommented, over engineered, full of bugs and full of magic. But we had the source. Finally, a light at the end of the tunnel. So I made this forum post about "**HLAPI Pro - a drop in replacement for UNET**". Fully compatible, just with a couple of bug fixes that I previously had to use reflection for. The idea was to offer people a 100% risk free alternative. Use HLAPI Pro to fix your bugs. Go back to the original DLLs any time. As far as I remember, Paul actually worked on MLAPI with TwoTen at first. But he convinced me to **MIT** License HLAPI Pro, and so Mirror was born. circle-info **Fun fact**: over the years we never really figured out the elephant in the room. How is that Unity pulled off this complex UNET technology, but then couldn't fix it? The weaver is a true piece of alien technology, and it's still not obvious to us who made that thing. When digging through it, at one point we found code for **NetworkView**. That component was actually part of Unity's legacy Raknet networking. As far as we can tell, UNET was based on their legacy system. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#meet-mirror) Meet Mirror ------------------------------------------------------------------------------------------------------------ During the next couple of years, we fixed several hundred UNET bugs and cleaned up the code. Still, nobody believed in UNET. Supposedly, the design didn't make sense, it would never scale and it would never work for any real game. The only people who believed in Mirror were those already using UNET for their projects, desperately needing bug fixes. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXGrddjbQAoQrhWGSfj%252F-MXGsIo2mV6LE1q-ZZE1%252F2017-08-13_stresstest.png%3Falt%3Dmedia%26token%3D4bf3f06c-d8f1-440b-9c5c-7ea5032789ed&width=768&dpr=3&quality=100&sign=a3f3181a&sv=2) Early Mirror stress test with hundreds of monsters At one point, we asked Unity for a donation seeing how we carried their whole UNET community for free. They told us UNET wouldn't have a future and it makes no sense to invest into that technology anymore. Our networking heroes had abandoned us, and told us our work was pointless. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#breaking-chains) Breaking Chains -------------------------------------------------------------------------------------------------------------------- Step by step, we broke all the chains that still tied us into UNET. * Someone open sourced the **Weaver** after a while, so we could fix it too. * We replaced the **LLAPI** black box with Telepathy. We've got heavy criticism for using TCP. But at least, the black box was finally open and we could fix bugs for once. Over the years, we've added many other transports like KCP. * Paul figured out how to use **HLAPI** as source drop in, without DLL replacements. * **Websockets** were previously closed in LLAPI, now finally open too. * The UNET **Community** mostly converted to Mirror too. Until today, most of our work on Mirror was about breaking the chains and fixing all the bugs. Here are some screenshots that we gathered over the years. Enjoy the nostalgia. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXH56tSO5iYzyoPu54G%252F-MXH5JIUU7nzMc9e8iVt%252F2017-08-05_patreon_header.png%3Falt%3Dmedia%26token%3D569ecc10-75cd-4ec6-9f1e-ebb6f596c0f6&width=768&dpr=3&quality=100&sign=90736b0d&sv=2) UNET Weaver Project / DLL ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXH56tSO5iYzyoPu54G%252F-MXH7f6uR38PiUeSenvx%252F2018-09-25_movedemo.png%3Falt%3Dmedia%26token%3De24839c7-2960-41e5-99f6-0c61b3b94c55&width=768&dpr=3&quality=100&sign=22241740&sv=2) Mirror's first example ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXH4l2XDdCmdO_oFGjg%252F-MXH54kGc2fgtDqOxA6H%252FScreenshot%2520at%2520Jul%252028%252013-09-17.png%3Falt%3Dmedia%26token%3D98b745d0-7087-428f-bdd0-97f0d3879035&width=768&dpr=3&quality=100&sign=ad0a015d&sv=2) HLAPI's first community test ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXH56tSO5iYzyoPu54G%252F-MXH6TskRJXujj7Fjtsy%252F2017-09-08_jagatai_stream.png%3Falt%3Dmedia%26token%3Dfd49285b-dec4-4a01-b083-b2c701fe4d46&width=768&dpr=3&quality=100&sign=f301e8d5&sv=2) Geno Online, jagatai's early MMO attempt with Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXGwHkZrWent2w8gSHT%252F-MXGwisRb5vPHtUo_w4g%252F2021-04-02_17-38-22%25402x.png%3Falt%3Dmedia%26token%3Db715292b-d23b-4520-a0af-afca93107aff&width=768&dpr=3&quality=100&sign=39dc803b&sv=2) uMMORPG 500 CCU test. UNET handled ~70 CCU when we started. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXGv9rdNs6BppEMZejB%252F-MXGvLZfSn2y44gSEY20%252F2020-10-12_20-45-17%2520-%2520x%2520branch%252020k%2520monsters%252019%2520FPS.png%3Falt%3Dmedia%26token%3D1d0384ba-8806-4b3b-a935-9f466677b416&width=768&dpr=3&quality=100&sign=3af7f195&sv=2) 20,000 monsters in Mirror. UNET handled 12 monsters back then. [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#community) Community -------------------------------------------------------------------------------------------------------- It's been 6 years since the UNET beta. Mirror has grown to 100,000 downloads a year, a fantastic Discord community with 10,000 users, new team members like our famous networking legend MrGadget, Coburn, James, katori, Lymdum, uwee and many more. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXGzoNVUHUgqhtOpoE9%252F-MXGzyW7wBd8cwK-s0pD%252F2021-04-02_17-52-33%25402x.png%3Falt%3Dmedia%26token%3D6c05b8d4-ad55-4d6c-a7a2-f26bf8ba10df&width=768&dpr=3&quality=100&sign=f60c1fee&sv=2) Several [popular gamesarrow-up-right](https://mirror-networking.com/showcase/) made with Mirror, and of course lots of [memesarrow-up-right](https://www.youtube.com/watch?v=jNTFFYhNhiI) . ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MXGwHkZrWent2w8gSHT%252F-MXGwRdCR1xQNCA0I1EX%252Fimage.png%3Falt%3Dmedia%26token%3Db410d12b-e473-44c3-ae1c-238da865a195&width=768&dpr=3&quality=100&sign=8130397c&sv=2) Population: ONE - made with Mirror [hashtag](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror#whats-next) What's Next ----------------------------------------------------------------------------------------------------------- We've spent all this time breaking the chains and fixing the bugs. Hundreds of them. But we also learned a lot about networking since then. In the future, our [roadmaparrow-up-right](https://trello.com/b/fgAE7Tud) is not so much about fixes anymore, but about core networking techniques. While stable, Mirror still has a long way to go and the original mission has never changed. We just need it for our games. circle-check **Mirror** required 10,000+ man hours on top of UNET. **UNET** was developed over several years, likely on top of Unity's **legacy** networking. **Legacy** networking must have been developed for years by people we don't even know. Mirror is standing on the **shoulders of giants**. It's hard to estimate how many years, man hours, sweat, tears went into this technology. [PreviousMirror Networkingchevron-left](https://mirror-networking.gitbook.io/docs) [NextGeneralchevron-right](https://mirror-networking.gitbook.io/docs/manual/general) Last updated 2 years ago --- # Mirror Networking | Mirror ![Page cover](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FnOZ83Xh7H4Dbx8HzMfU7%252Fwe6li1x%255B1%255D.png%3Falt%3Dmedia%26token%3D229ec1c7-9083-4112-8622-3934188aa0db&width=1248&dpr=3&quality=100&sign=1a2ceea1&sv=2) circle-check **Stop worrying about networking because we do.** We needed a networking library that allows us to [**launch our games**arrow-up-right](https://github.com/MirrorNetworking/Mirror#made-with-mirror) and **survive the next decade**. [**Mirror**arrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) is a **high level** Networking library for Unity, optimized for **ease of use** & **probability of success**. * Compatible with over a dozen low level [**Transports**](https://mirror-networking.gitbook.io/docs/manual/transports) . * Growing library of [**Script Templates**](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) to make learning and coding easier. * Remote Procedure calls and context control via [**Attributes**](https://mirror-networking.gitbook.io/docs/manual/guides/attributes) . * More than a dozen built in [**Components**](https://mirror-networking.gitbook.io/docs/manual/components) . * Five flavors of [**Interest Management**](https://mirror-networking.gitbook.io/docs/manual/interest-management) , and you can make your own custom version. * Support for [**Additive Scenes**](https://mirror-networking.gitbook.io/docs/manual/examples) with Physics Isolation (battle instances, levels, etc.) * Several complete [**Examples**](https://mirror-networking.gitbook.io/docs/manual/examples) included. * Constant improvements and enhancements [**every month**](https://mirror-networking.gitbook.io/docs/manual/general/changelog) **.** * Full time support available in our [**Discord**arrow-up-right](https://discord.gg/2BvnM4R) . [hashtag](https://mirror-networking.gitbook.io/docs#unity-versions) Unity Versions --------------------------------------------------------------------------------------- We will follow Unity's support for **LTS releases**. Any version beyond those may work, but you're on your own, especially with regard to preview / beta versions. At the moment, we recommend using Unity 2020 or 2021 LTS releases. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F4F3v3IaUCPsMrO6iU7oa%252FTimeline.webp%3Falt%3Dmedia%26token%3D47d302ec-3c00-46ae-a648-ef26c29df423&width=768&dpr=3&quality=100&sign=3ee21e05&sv=2) Unity LTS Release Schedule [NextA Brief History of Mirrorchevron-right](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror) Last updated 1 year ago --- # General | Mirror Mirror is a system for building multiplayer capabilities for Unity games. It is built on top of the lower level transport real-time communication layer, and handles many of the common tasks that are required for multiplayer games. While the transport layer supports any kind of network topology, Mirror is a server authoritative system; although it allows one of the participants to be a client and the server at the same time, so no dedicated server process is required. Working in conjunction with the internet services, this allows multiplayer games to be played over the internet with little work from developers. Mirror is focused on ease of use and iterative development and provides useful functionality for multiplayer games, such as: * Message handlers * General purpose high performance serialization * Distributed object management * State synchronization * Network classes: Server, Client, Connection, etc Mirror is built from a series of layers that add functionality: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MULwtHEL2S_ReLN73jX%252F-MULxubN-V0m_Gl-KJEB%252Fimage.png%3Falt%3Dmedia%26token%3Db44a351f-7cca-470c-8526-372e2b27c835&width=768&dpr=3&quality=100&sign=34ee40fb&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/general#server-and-host) Server and Host -------------------------------------------------------------------------------------------------------- Mirror multiplayer games include: * **Server** A server is an instance of the game which all other players connect to when they want to play together. A server often manages various aspects of the game, such as keeping score, and transmit that data back to the client. * **Clients** Clients are instances of the game that usually connect from different computers to the server. Clients can connect over a local network, or online. A client is an instance of the game that connects to the server, so that the person playing it can play the game with other people, who connect on their own clients. The server might be either a “dedicated server”, or a “host server”. * **Dedicated server** This is an instance of the game that only runs to act as a server. * **Host server** When there is no dedicated server, one of the clients also plays the role of the server. This client is the “host server”. The host server creates a single instance of the game (called the host), which acts as both server and client. The diagram below represents three players in a multiplayer game. In this game, one client is also acting as host, which means the client itself is the “local client”. The local client connects to the host server, and both run on the same computer. The other two players are remote clients - that is, they are on different computers, connected to the host server. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MULwtHEL2S_ReLN73jX%252F-MULxz4-e3LKPZX6b07I%252Fimage.png%3Falt%3Dmedia%26token%3D9b4e49e9-98d7-4b2f-a39b-7ddc47e73b6f&width=768&dpr=3&quality=100&sign=656c8a5f&sv=2) The host is a single instance of your game, acting as both server and client at the same time. The host uses a special kind of internal client for local client communication, while other clients are remote clients. The local client communicates with the server through direct function calls and message queues, because it is in the same process. It actually shares the Scene with the server. Remote clients communicate with the server over a regular network connection. When you use Mirror’s, this is all handled automatically for you. One of the aims of the multiplayer system is for the code for local clients and remote clients to be the same, so that you only have to think about one type of client most of the time when developing your game. In most cases, Mirror handles this difference automatically, so you should rarely need to think about the difference between your code running on a local client or a remote client. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general#instantiate-and-spawn) Instantiate and Spawn -------------------------------------------------------------------------------------------------------------------- When you make a single player game In Unity, you usually use the `GameObject.Instantiate` method to create new game objects at runtime. However, with a multiplayer system, the server itself must “spawn” game objects in order for them to be active within the networked game. When the server spawns game objects, it triggers the creation of game objects on connected clients. The spawning system manages the lifecycle of the game object, and synchronizes the state of the game object based on how you set the game object up. For more details about networked instantiating and spawning, see documentation on Spawning [GameObjects](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/general#players-and-local-players) Players and Local Players ---------------------------------------------------------------------------------------------------------------------------- Mirror handles player game objects differently to non-player game objects. When a new player joins the game (when a new client connects to the server), that player’s game object becomes a “local player” game object on the client of that player, and Mirror associates the player’s connection with the player’s game object. Mirror associates one player game object for each person playing the game, and routes networking commands to that individual game object. A player cannot invoke a command on another player’s game object, only their own. For more details, see documentation on Player [GameObjects](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/general#authority) Authority -------------------------------------------------------------------------------------------- Servers and clients can both manage a game object’s behavior. The concept of “authority” refers to how and where a game object is managed. Mirror is based around “server authority” as the default state, where the Server has authority over all game objects. Player game objects are a special case and treated as having “local authority”. You may want to build your game using a different system of authority - for more details, see [Network Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority) . [PreviousA Brief History of Mirrorchevron-left](https://mirror-networking.gitbook.io/docs/trivia/a-history-of-mirror) [NextGetting Startedchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/getting-started) Last updated 2 years ago * [Server and Host](https://mirror-networking.gitbook.io/docs/manual/general#server-and-host) * [Instantiate and Spawn](https://mirror-networking.gitbook.io/docs/manual/general#instantiate-and-spawn) * [Players and Local Players](https://mirror-networking.gitbook.io/docs/manual/general#players-and-local-players) * [Authority](https://mirror-networking.gitbook.io/docs/manual/general#authority) --- # Getting Started | Mirror This document describes steps to creating a multiplayer game with Mirror. The process described here is a simplified, higher level version of the actual process for a real game; it doesn’t always work exactly like this, but it provides a basic recipe for the process. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#video-tutorials) Video Tutorials ------------------------------------------------------------------------------------------------------------------------ Check out these [awesome videos](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials) showing you how to get started with mirror. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#script-templates) Script Templates -------------------------------------------------------------------------------------------------------------------------- * Create new Network Behaviours and other common scripts faster See [Script Templates](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#networkmanager-set-up) Network Manager Setup ------------------------------------------------------------------------------------------------------------------------------------ * Create a new Network Manager from the [Assets > Create > Mirror](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) menu. * Add a new game object to the Scene and rename it “NetworkManager”. * Add the newly created Network Manager component to the “NetworkManager” game object. * Add the [NetworkManagerHUD](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud) component to the game object. This provides the default UI for managing the network game state. See [Using the NetworkManager](https://mirror-networking.gitbook.io/docs/manual/components/network-manager) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#player-prefab) Player Prefab -------------------------------------------------------------------------------------------------------------------- * Find the Prefab for the player game object in the game, or create a Prefab from the player game object * Add the NetworkIdentity component to the player Prefab * Set the `Player Prefab` in the NetworkManager’s Spawn Info section to the player Prefab * Remove the player game object instance from the Scene if it exists in the Scene See [Player Objects](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/player-gameobjects) for more information. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#player-movement) Player Movement ------------------------------------------------------------------------------------------------------------------------ * Add a NetworkTransform component to the player Prefab * Check the Client Authority checkbox on the component. * Update input and control scripts to respect `isLocalPlayer` * Override OnStartLocalPlayer to take control of the Main Camera in the scene for the player. For example, this script only processes input for the local player: [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#basic-player-game-state) Basic player game state ---------------------------------------------------------------------------------------------------------------------------------------- * Make scripts that contain important data into Network Behaviours instead of MonoBehaviours * Make important member variables into SyncVars See [State Synchronization](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#networked-actions) Remote Actions ------------------------------------------------------------------------------------------------------------------------- * Make scripts that perform important actions into Network Behaviours instead of MonoBehaviours * Update functions that perform important player actions to be commands See [Remote Actions](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#non-player-game-objects) Non-player GameObjects --------------------------------------------------------------------------------------------------------------------------------------- Fix non-player prefabs such as enemies: * Add the NetworkIdentity component * Add the NetworkTransform component * Register spawnable Prefabs with the NetworkManager * Update scripts with game state and actions [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#spawners) Spawners ---------------------------------------------------------------------------------------------------------- * Potentially change spawner scripts to be NetworkBehaviours * Modify spawners to only run on the server (use isServer property or the `OnStartServer()` function) * Call `NetworkServer.Spawn()` for created game objects [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#spawn-positions-for-players) Spawn positions for players ------------------------------------------------------------------------------------------------------------------------------------------------ * Add a new game object and place it at player’s start location * Add the NetworkStartPosition component to the new game object [PreviousGeneralchevron-left](https://mirror-networking.gitbook.io/docs/manual/general) [NextScript Templateschevron-right](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) Last updated 3 years ago * [Video Tutorials](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#video-tutorials) * [Script Templates](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#script-templates) * [Network Manager Setup](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#networkmanager-set-up) * [Player Prefab](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#player-prefab) * [Player Movement](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#player-movement) * [Basic player game state](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#basic-player-game-state) * [Remote Actions](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#networked-actions) * [Non-player GameObjects](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#non-player-game-objects) * [Spawners](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#spawners) * [Spawn positions for players](https://mirror-networking.gitbook.io/docs/manual/general/getting-started#spawn-positions-for-players) Copy using UnityEngine; using Mirror; public class Controls : NetworkBehaviour { void Update() { // exit from update if this is not the local player if (!isLocalPlayer) return; // handle player input for movement } } --- # Script Templates | Mirror circle-info As of August 2023, Unity Asset Store does not allow us to upload ScriptTemplates anymore. Import this package to add them to your project. * You must **restart Unity** after importing this package for Unity to wire up the menus. file-archive 13KB [ScriptTemplates.zip](https://462154250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MGmQrf2z6FL0ZpExPAn%2Fuploads%2FiZe72HK3G2onyiZgTc4d%2FScriptTemplates.zip?alt=media&token=ff1a0351-b91b-4f3a-9818-00f91a9ee9ca) archive downloadDownload[arrow-up-right-from-squareOpen](https://462154250-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MGmQrf2z6FL0ZpExPAn%2Fuploads%2FiZe72HK3G2onyiZgTc4d%2FScriptTemplates.zip?alt=media&token=ff1a0351-b91b-4f3a-9818-00f91a9ee9ca) ScriptTemplates Unity Package circle-exclamation **Root Folder Required:** ScriptTemplates is a special folder to Unity and must remain in the Assets folder. We've added Script Templates to make it easier to create derived class scripts that inherit from our base classes. * All possible overrides are already made for you and organized. * They're all fully commented as to what they all do. * Base method calls are all in place where needed so you can see what they already do. * Each has links at the top to their doc page(s). The **Mirror** section will appear under the **Assets > Create menu**, as well as the context menu that comes up when you right-click on any folder in your project. You'll be prompted for the file name like any other asset creation. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FhHwwn4r7c9cZ0etctypU%252Fimage.png%3Falt%3Dmedia%26token%3D550ede85-1850-4e98-b850-146b342523c4&width=768&dpr=3&quality=100&sign=3c2ba9bc&sv=2) Menu to Mirror Script Templates Hopefully these templates will be helpful to new users of Mirror to learn what methods are available in various classes, as well as just being more convenient for everyone. [PreviousGetting Startedchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/getting-started) [NextChange Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog) Last updated 1 year ago --- # 2025 Change Log | Mirror circle-info Mirror is published to the [Asset Storearrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) at the start of every month, unless some critical issue causes a delay. circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#v96.0.1-2025-feb-27) [v96.0.1arrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) -- 2025-Feb-27 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#added) Added * [Hex Spatial Hash Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing) 2D and 3D with additional optimizations. * Network Manager now has a Clear button for spawnable prefabs. * Scene Distance Interest Management (combines Scene and Distance IM's). * Interest Management SetHostVisibility now handles terrains with tree details, lights, audio sources, and particle systems correctly. * NetworkTransform now exposes `velocity` and `angularVelocity` on the receiving side. * Encryption Transport now logs hardware accelleration status. * PlayerControllerRB in example controllers: uses non-kinematic rigidbody instead of Character Controller. * Vector4Long implemented for quarternions delta compression. * Half Floats for Quaternion compression. * Entering play mode while in prefab edit mode works now. * HashSet is now supported in SyncVar / Command / ClientRpc / TargetRpc / NetworkMessage. * NetworkIdentity.OnDestroy verifies spawned\[netId\] before removing. * NetworkTransformHybrid that emits Reliable full state on a slow interval and Unreliable deltas in between. * PlayerTest example now has PlayerContollerHybrid prefab for testing. * PickupsDropsChilds example now has interface implemented to show how that should be done. * HashSet is now a supported type for SyncVar / Cmd / Rpc. * HalfFloats added to Compression. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#fixes) Fixes * NetworkClient now defers spawn payload until after all objects have been created, eliminating many common race conditions. * Fixed bug in 96.0.1 for missing message.payload.count check. * Reader / Writer Processor now works across assemblies. * Simple Web Transport jslib improved to support more platforms. * Network Manager StopClient no longer calls OnClientDisconnectInternal (Transport calls it). * NetworkServer now correctly calls NetworkClient.InvokeUnSpawnHandler from UnSpawnInternal * NetworkAnimator no longer double calls HandleAnimSetTrigger / HandleAnimResetTrigger on host client. * NetworkTransform now calls Physics.SyncTransforms in ResetState, which is called from OnTeleport, making it easier to teleport without special handling for character controllers and non-kinematic rigidbodies that would resist being repositioned. * NetworkTransform now supports FixedUpdate, so non-kinematic rigidbody players don't stutter. * All forms of Interest Management now use LateUpdate. * Netgraph improvements. * Examples updated. * Edgegap Plugin updated to 2.3.1. * Encryption Transport now implements Port Transport. * Network Server now checks `listen` and rejects connections if not listening. * KCP handles nulls in OnClientError during shutdown better now. * Room and Multiple Additive Scene examples now demonstrate Pooling (See Spawner and Reward scripts). * Portal script in Additive Levels example now properly waits for RemovePlayerForConnection to complete. * PredictionUtils now correctly sets freeze rotation before constraints. * Entering playmode when in prefab edit mode is no longer prevented (now it works). ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#changes) Changes * NetworkClient, for initial spawning, now defers applying spawn payload until after instantiating all networked objects and adding them into the `spawned` dictionary. This means SyncVars and Sync\* collections that cross-reference other networked objects should be much more robust, as the long-standing race condition should now be eliminated. * Network Server `dontListen` renamed to `listen` to eliminate double negative bool. * Moved connectionId to NetworkConnectionToClient (it's meaningless on clients). * Deprecated Network Manager's virtual OnApplicationQuit - Use OnDestroy instead. * Deprecated Transport's virtual OnApplicationQuit - Use OnDestroy instead. * Deprecated Snapshot interpolation settings in Network Client in favor of SnapShotSettings. * Bouncy Castle moved to Encryption Transport folder. [PreviousChange Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog) [Next2024 Change Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log) Last updated 3 months ago * [v96.0.1 -- 2025-Feb-27](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#v96.0.1-2025-feb-27) * [Added](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#added) * [Fixes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#fixes) * [Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log#changes) --- # Change Log | Mirror circle-info Mirror is published to the [Asset Storearrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) at the start of every month, unless some critical issue causes a delay. circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog#v97.0.0-in-progress) [v97.0.0arrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) -- In Progress ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog#added) Added * NetworkTransform now has dropdown for using Update/FixedUpdate/LateUpdate * RemoteStatistics now has option to skip password and auth check for convenient testing * Mirror Render Pipeline Converter for URP compatibility * NetworkName component: syncs object name from server to clients * NetworkBehaviour::isHost shortcut for isServer + isClient * UniqueNameAuthenticator: reusable version from the Chat example * Card Game example with simple match making and tight data flow ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog#fixes) Fixes * Network Authenticator UnityEvents improved and Unity 2019 compatibility restored * Predicted Rigidbody no longer resets ghost objects * NetworkScenePostProcess now only processes the last loaded scene instead of all loaded scenes for better performance * NetworkServer / NetworkClient exceptionsDisconnect now is reset during Shutdown * NetworkManager now unsubscribes from OnSceneLoaded in OnDestroy * Some common code in various NetworkTransform flavors consolidated to NetworkTransformBase * NetworkTransform now handles changing SendIntervalMultiplier at runtime * NetworkTransform::OnTeleport no longer breaks delta compression * NetworkTransformHybrid now better handles initial child sync * NetworkAnimator Trigger message handling improved * SimpleWebTransport now includes Port in ToString * SimpleWebTransport now includes timestamps in log outputs * SimpleWebTransport general improvements in logging * SimpleWebTransport minimized calls to conn.Dispose * InterestManagement now hides WorldSpace Canvas in SetHostVisibility * Host client now respects AOI when invoking SyncVar hooks and SyncCollection Actions * SyncVar hooks and SyncCollection Actions are now deferred on clients until end of initial spawn * This should eliminate race conditions when attempting to cross-reference other networked objects from the hooks and Action handlers. * OnGUI now properly excluded from Dedicated Server builds * ReadOnly attribute now supports TextArea fields * NetworkIdentity::AssignClientAuthority now ensures owner data is included * CecilX updated with missing namespaces and build fixes * ThreadLog now only captures logging from Mirror threads * Transport base class now has a `TryBuildValidUri` helper method to protect against unvalid characters in host names, and our transports have been updated to use it from `ServerUri` overrides. * NetworkManager no longer throws NRE from StopHost after StartHost failed * Many examples have been updated, especially PlayerTest prefabs and controllers ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog#changes) Changes * NetworkAnimator: Deprecated clientAuthority for syncDirection * Simple Web Transport no longer supports Unity 2021 and older * **BREAKING**: Commands invoked by host client bypass network writer / reader * This makes the host client timing different from remote clients * This now requires careful testing with remote clients that may act differently [PreviousScript Templateschevron-left](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) [Next2025 Change Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log) Last updated 3 months ago * [v97.0.0 -- In Progress](https://mirror-networking.gitbook.io/docs/manual/general/changelog#v97.0.0-in-progress) * [Added](https://mirror-networking.gitbook.io/docs/manual/general/changelog#added) * [Fixes](https://mirror-networking.gitbook.io/docs/manual/general/changelog#fixes) * [Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog#changes) --- # Execution Order | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MfBMBm_D1F9HcRyy0MD%252F-MfBMPNFjGslLHG0cxTV%252Fimage.png%3Falt%3Dmedia%26token%3D5054c40b-aaaa-4389-8873-f980ccdf0c00&width=768&dpr=3&quality=100&sign=3eee1a11&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MfBMBm_D1F9HcRyy0MD%252F-MfBMUtFf9NUy8mba-mD%252Fimage.png%3Falt%3Dmedia%26token%3Da3cfcdea-b0b5-4556-a4b1-04a6a53eaa54&width=768&dpr=3&quality=100&sign=ebce08a5&sv=2) [PreviousFAQchevron-left](https://mirror-networking.gitbook.io/docs/manual/faq) [NextTransportschevron-right](https://mirror-networking.gitbook.io/docs/manual/transports) Last updated 4 years ago --- # 2024 Change Log | Mirror circle-info Mirror is published to the [Asset Storearrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) at the start of every month, unless some critical issue causes a delay. circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v93.0.0-2024-oct-5) [v93.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v93.0.0) - 2024-Oct-5 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added) Added * Unity 6 Compatibility. * PlayerContollers have been overhauled and examples updated. * ServerTeleport added to NetworkTransform. * Ping/Traffic/FPS Graphs. * PickupsDropsChilds example with Robot Kyle created. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes) Fixes * Edgegap Plugin updated to 1.0.8. * Simple Web Transport improved logging and removed allocations. * Telepathy Transport now has more robust error handling in GetClientAddress. * ReadOnly attribute now works for properties too. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes) Changes ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#breaking-changes) Breaking Changes * NetworkTransform sendIntervalMultiplier replaced by syncInterval math. * Older obsoletes removed. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v90.0.0-2024-aug-2) [v90.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v90.0.0) - 2024-Aug-2 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added-1) Added * TopDown Shooter example created. * AutoLAN exxample created. * NetworkRuntimeProfiler implemented. * OnServerConnectedWithAddress implemented for all Transports. * Network Manager now has `offlineSceneLoadDelay` to allow showing a UI message before loading the offline scene. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes-1) Fixes * GetPositionAndRotation extension now excluded for 2022.0 or newer. * Edgegap Plugin updated to 1.0.1. * NetworkServer.Destroy no longer calls ResetState on prefabs so isServer is preserverd for OnDestroy. * NetworkBehaviour now checks for non-zero netId before attempting to invoke Commands. * NetworkServer now removes default OnTransportConnectedWithAddress handler in RemoveTransportHandlers. * Simple Web Transport now supports https URI scheme. * TimeSnapshotMessage no longer requires authority. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes-1) Changes * Bouncy Castle now has new namespace and GUID. * Simple Web Transport default setup now assumes reverse proxy will be used. * OnServerConnected has been deprecated in favor of OnTransportConnectedWithAddress. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v89.80-2024-jun-13) [v89.80arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v89.8.0) - 2024-Jun-13 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added-2) Added * Transport: `IsEncrypted` and `EncryptionCypher` virtual methods. * Encryption Transport implements`IsEncrypted` & `EncryptionCypher` . * Simple Web Transport implements`IsEncrypted` & `EncryptionCypher` . * Edgegap Lobby Transport & Demo. * Transport Exception Actions have been reimplemented. * SpatialHashing3D for XYZ to include vertical axis in checks. * Implement PortTransport for LatencySimulation since almost all underlying Transports are PortTransports. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes-2) Fixes * Weaver Custom Read / Write methods for Serialization now works across assembly definitions. * EdgegapKcp StopHost() null reference exception. * EdgegapHosting now only includes enabled scenes in builds. * ILPostProcessorAssemblyResolver now ignores Bee.BeeDriver better. * Simple Web Transport now locally scopes `websocket` and `Runtime`. * Latency Simulation had a bunch of minor bugs. * Missing overrides added to Network Rigidbody components. * Network Manager's OnGUI now wrapped in `DEBUG` compiler symbol. * NetworkServer now correctly spawns player for owner client when Visibility is Force Hidden. * Network Animator now defaults animatorSpeed to 1 so SyncVar works correctly. * NetworkTransform components auto-assign their own GO if target is unassigned. * Pool now checks for nulls when returning and discards. * Batches are now properly returned to NetworkWriterPool before destroying the connection * GetSyncVarNetworkBehaviour now validates componentIndex and logs detailed error instead of IndexOutofRangeException. * Sync\* Collections now have pretty names in inspector. * version file is now included in release packages with correct version. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes-2) Changes * `LagCompensator` attributes updated and custom inspector added. * Remote Statistics default hotkey changed to backtick ( `` ` `` ). * Continued improvements to `Prediction` and `PredictedRigidbody`. These are still considered as experimental features. * SyncDictionary, SyncList, and SyncSet all now call their Clear operations **after** invoking the Callback, so users can iterate the collection in the callback hander. * SyncDictionary, SyncList, and SyncSet all now have individual Actions that users can subscribe to directly. * **NOTE:** Some Actions pass the **OLD** values where appropriate, so be careful with your implementations. Also note that these new actions replace the generic Callback Action that is now obsolete and will be removed later in the year. * KCP Transport updated to version 1.41. * Moved GetClientAddress exception handling from Transport into Telepathy itself. * NetworkServer.RemovePlayerForConnection now has RemovePlayerOptions. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v89.0.0-2024-mar-05) [v89.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v89.0.0) -- 2024-Mar-05 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added-3) Added * `GetFunctionMethodName` added to `RemoteProcedureCalls`. * `NetworkClient` `RegisterHandler` now takes `ChannelId` parameter. * `NetworkServer` and `NetworkClient` now have `ReplaceHandler` with `ChannelID` parameter. * SyncVar now supports arrays. * `NetworkTime.SendPing` method for `NetworkClient` to call from `OnTransportConnected`. * NetworkTransform-Unreliable only send changed data for improved bandwidth usage. * [Lag Compensator](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation) as convenience component that wraps all the Lag Compensation logic. * [Encryption Transport](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport) as chained transport. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes-3) Fixes * `NetworkServer.RemovePlayerForConnection` now uses `NetworkConnectionToClient`. * `NotReadyMessage` no longer requires authenticated client. * `InterestManagementBase` `OnEnable` no longer shows error when called multiple times. * Match and Team Interest Management overhauled for better performance. * `NetworkAnimator` now initializes state in `OnEnable`. * `NetworkAnimator` now always serializes and deserializes the exact amount of data. * `NetworkAnimator` `ClientRpc` now has `includeOwner = false`. * NetworkServer.SendToAll/Observers/ReadyObservers now validates packet size while is still known. * NetworkTransform-Unreliable Quaternion compression. * `NetworkManager.ServerChangeScene` now prevents client from calling. * `NetworkManager` no longer forces `networkAddress` to `localhost` on server builds. * Multiplexer now avoids `KeyNotFoundException`. * NetworkServer and NetworkClient respect exceptionDisconnect. * Now uses `FindAnyObjectByType` for later Unity versions. * `NetworkServer.Destroy` refactored. * `NetworkServer.Spawn` now activates inactive GameObjects (in case Unspawned). ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes-3) Changes * KCP Transport updated to version 1.40. * `InterestManagement` now has separate `ResetState` from `Reset`. * `NetworkTransform` now has separate `ResetStat`e from `Reset`. * `NetworkTransform` Sync Direction now defaults to Client To Server. * `NetworkAnimator` Sync Direction now defaults to Client To Server. * `NetworkRigidbody` Sync Direction now defaults to Client To Server. * `onlySyncOnChange` and `compressRotation` moved to `NetworkTransformBase`. * Extensive improvements to `Prediction` and `PredictedRigidbody`...still experimental. * Examples Updated. * [Script Templates](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) Updated. * Edgegap Hosting Updated. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#breaking-changes-1) Breaking Changes * `NetworkIdentity` `visible` renamed to `visibility`. [Previous2025 Change Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2025-change-log) [Next2023 Change Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log) Last updated 1 year ago * [v93.0.0 - 2024-Oct-5](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v93.0.0-2024-oct-5) * [Added](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added) * [Fixes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes) * [Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes) * [Breaking Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#breaking-changes) * [v90.0.0 - 2024-Aug-2](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v90.0.0-2024-aug-2) * [Added](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added-1) * [Fixes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes-1) * [Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes-1) * [v89.80 - 2024-Jun-13](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v89.80-2024-jun-13) * [Added](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added-2) * [Fixes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes-2) * [Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes-2) * [v89.0.0 -- 2024-Mar-05](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#v89.0.0-2024-mar-05) * [Added](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#added-3) * [Fixes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#fixes-3) * [Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#changes-3) * [Breaking Changes](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log#breaking-changes-1) --- # 2023 Change Log | Mirror circle-info Mirror is published to the [Asset Storearrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) at the start of every month, unless some critical issue causes a delay. circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v86.13.4-2023-dec-24) [v86.13.4arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v86.13.4) -- 2023-Dec-24 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: In certain conditions, KCP would flood timeout warnings. * Fixed: Compress Rotation on `NetworkTransform` now correctly considers Local or World coordinates. * Fixed: `NetworkPingDisplay` made a bit wider so RTT wouldn't be cut off. * Fixed: Several updates to `PredictedRigidbody` and materials handling * Fixed: `PredictedRigidbody` Visual rotation interpolation now works correctly. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v86.13.0-2023-dec-12) [v86.13.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v86.13.0) -- 2023-Dec-12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: `NetworkDiagnosticsDebugger` to log messages sent and received. * Added: `NetworkPingDisplay` now shows Connection Quality. * Added: `PredictedRigidbody` visual interpolation object. * Added: LayerMask support in Network Reader / Writer * Added: Network Manager now has toggle to disable Auto-Start Headless Server / Client in Editor. * Added: Network Manager now has toggle to not disconnect client on message exceptions. * Added: Network Manager now has a Populate Spawnable Prefabs button. * Added: Utils now has `isWebGL` and `isDebug`. * Added: SimpleWebTransport now returns remote address from reverse proxy when available. * Added: Additional examples have been added. * Fixed: Edgegap Hosting registry, image name, and tag strings are trimmed to avoid errors from trailing whitespace. * Fixed: SyncVar hook invocations no longer instantiate a new Action delegate on every call. * Fixed: Ping messages now include scene hash to prevent high RTT after long scene load. * Fixed: `NetworkTransform` `OnTeleport` no longer calls `Reset`, which cause `NT Reliable` deltas to get out of sync. * Fixed: `NetworkBehaviour` `authority` now correctly evaluates for host client. * Fixed: `LatencySimulation` now correctly applies latency to both channels. * Fixed: Message ID hashing improved to minimize collisions. * Changed: EdgeGap Plugin updated to version 2. * Changed: Network Manager Auto-Start Headless was refactored. * Changed: Multiplex Transport is now a `PortTransport`. * Changed: Some examples now use `NetworkTransformReliable`. * Changed: `NetworkTransformReliable` now has toggle for rotation compression. * Changed: `NetworkTransformReliable` now always uses bandwidth savings. * Changed: Some duplicated scripts in Examples consolidated to \_Common folder. * Changed: `ConnectionQuality` moved to `NetworkClient`. * Changed: `GUIConsole` layout updated to not collide with `NetworkHUD`. * Default hotkey changed to tick (`` ` ``) for safer use in WebGL builds. * Changed: KCP Transport `ToString` now include port. * Changed: Telepathy Transport `ToString` has been simplified and shortened. * Changed: KCP and Telepathy transports now use compiler symbols in `Available` check. * Changed: KCP Transport updated to version 1.39. * Changed: Various example have been updated. * Changed: [Script Templates](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) have been updated. * **Breaking Changes** * SimpleWebTransport Settings and Logging have been refactored. * There are now separate port fields for server and clients so you don't have to change them for building server and client. * SimpleWebTransport Use of cert.json and SSL certs has been labeled as obsolete in the component inspector. * This feature will be removed eventually. Reverse Proxy should always be implemented as it performs far better and is easier to maintain. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v81.4.0-2023-aug-03) [v81.4.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v81.4.0) -- 2023-Aug-03 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Examples: added BenchmarkIdle demo to test with 80% idle objects * feature: NetworkTransform WorldScale option * NetworkClient: improve 'did not find target for sync message' warning * fix: SimpleWebTransport conditionals removed so users can see error m… * kcp2k V1.37 \[2023-07-31\] * Unity 2021.3.29 LTS for latest fixes * feature: HistoryBounds MVP (#3563) * Tanks co-op example, take control of vehicles via Mirrors Authority a… * fix: NetworkReader ReadBytes/Array/List allocation limit to pre… * remove unused import * NetworkWriter: clean up old UIntDouble comments * NetworkReader/Writer Read/WriteList: comments * fix: NetworkConnection "cannot send packet larger than ..." message n… * fix: NetworkMessages.MaxContentSize now considers channelId instead o… * feature: bring back NetworkServer.disconnectInactiveConnections (#3556) * fix: remove redundant RPC buffering. saved bandwidth, but introduced … * fix: NetworkIdentity.AssignAssetId() is now saved properly. fixes a b… * fix: NetworkTime RTT now checks for malicious timestamps from the future * Compression: remove unnecessary QuaternionElement function * Compression: more obvious TenBitsMax representation * feature: NetworkConnectionToClient.rtt via Ping & Pong Messages (#3545) * Examples: default send rate increased from 30 Hz to 60 Hz for remaini… * perf: default send rate increased from 30 Hz to 60 Hz for users to ge… * Tanks demo: increase send rate from 30 Hz to 120 Hz to avoid rtt bein… * NetworkBehaviour.OnValidate: GetComponentInParent(bool) 2020 support … * NetworkIdentity: correct GetComponentInParent explanations (credit: F… * NetworkIdentity: expose AssetGuidToUint in builds * fix: NetworkBehaviour.OnValidate can't find parent NetworkIdentity be… * fix: Tanks demo: replace Turret obsolete NetworkTransform with Networ… * perf: remove some unnecessary inlining to optimize instruction cache * NetworkIdentity: expose AssetId to Guid translation function * fix: 2019 tests work again (#3547) * fix: NetworkBehaviour OnValidate #ifdef adjusted for Unity 2020.3.19 … * improve error message for #3525 for cases where the \[SyncVar\] is name… * fix NetworkIdentityTests by applying the workaround for #3525 * fix: #3525 by explaining the solution in the Error message. * NetworkClient OnGUI: better rtt display * breaking: NetworkTime.PingFrequency renamed to PingInterval. Makes it… * fix PrepareToSpawnSceneObjects tests after recent fix * NetworkTime: more readable ping interval check * fix: #3538 calling unspawn on scene objects in DestroyOwnedObjects (#… * fix: PrepareToSpawnSceneObjects checks netId instead of activeSelf \[f…\ \ * feature: Lag Compensation V1 (#3534)\ \ * Tests: fix failing NetworkManagerTests because DeeplyTested test didn…\ \ * NetworkTime: rttVar renamed to rttVariance for consistency with old M…\ \ * fix: SnapshotInterpolation.Insert() now has a bufferLimit to avoid ev…\ \ * perf: NetworkTransformBase SortedLists now allocate with a default ca…\ \ * Readme updated: clarify incentives, fix typos, improve formatting\ \ * feature: ConnectionQuality Heuristic + Callback + GUI (#3526)\ \ * NetworkTime: reintroduce Round Trip Time Variance to prepare for Conn…\ \ * NetworkClient: initialBufferTime for debugging, comparisons, and to p…\ \ * Tanks demo: always show time interpolation GUI for easier debugging\ \ * fix: NetworkClient TimeInterpolation: add 'current' bufferTimeMultipl…\ \ * Disable the failing tests for now, so at least the project compiles w…\ \ * fix: Weaver SyncVarAttributeAccessReplacer now detects modifying \[Syn…\ \ * Weaver: SyncVarAccessReplacer: pass Logging\ \ * Weaver: SyncVarAccessReplacer: syntax & comments to make it more obvious\ \ * fix: Weaver now weaves NetworkBehavious in nested type definitions\ \ * feature: Weaver adds 'bool Weaved()' to each NetworkBehaviour, which …\ \ * Tests: remove unused 'using'\ \ * fix: tests work on Unity 2022.2+ \[imer\]\ \ * Weaver ILPostProcessorAssemblyResolver: use GetFileNameWithoutExtension\ \ * perf: Weaver ILPostProcessorAssemblyResolver FindFile searches dllnam…\ \ * Weaver: ILPostProcessorAssemblyResolver FindFile comments\ \ * Weaver: ILPostProcessorAssemblyResolver caches FindFile for a 50x imp…\ \ * perf: Weaver ILPostProcessorAssemblyResolver FindFile caches exeName,…\ \ * Weaver ILPostProcessorAssemblyResolver: FindFile uses string name par…\ \ * perf: Weaver ILPostProcessorAssemblyResolver uses ConcurrentDictionar…\ \ * RigidbodyPhysics demo: disable 'onlySyncOnChange' until #3519 is fixed\ \ * Examples/VR link\ \ * Unbatcher: Unity 2019 fix\ \ * fix: Batching VarInt size header added to fix custom serializated Net…\ \ * feature: NetworkRigidbody Benchmark demo\ \ * fix: NetworkRigidbody/2D now uses .target's Rigidbody and supports ch…\ \ * NetworkRigidbody: MovePosition overwrite comments\ \ * feature: NetworkMessageId <> Type lookup and log function for debuggi…\ \ * Unbatcher: simplify GetNextMessage\ \ * feature: VarInt size prediction\ \ * NetworkMessages: keep GetId for convenience\ \ * breaking: NetworkTransform renamed to NetworkTransformUnreliable for …\ \ * remove duplicate NetworkRigidbody scripts\ \ * NetworkTransform: moved all related scripts into one NetworkTransform…\ \ * perf: NetworkRigidbody Reliable/Unreliable via NetworkTransform for s…\ \ * fix: NetworkBehaviourInspector 'had no target' warning\ \ * Readme: Information Security Guidelines\ \ * NetworkTransform: show Gizmos as WriteCube instead of solid Cube for …\ \ * Rigidbody Example: gray background so we can see overlays easier\ \ * Rigidbody Example: show time interpolation GUI\ \ * RigidbodyPhysics Example: fix missing component warnings\ \ * fix: Weaver runtime fuse to ensure weaving succeeded before starting …\ \ * Snapshot Interpolation Example: README\ \ * CompilationFinishedHook: add explanation\ \ * fix NetworkClientTests for Unity 2019\ \ * NetworkMessages.WrapHandler: improve log message to make it easier to…\ \ * fix: NetworkClient unbatcher is now reset in host mode connect as wel…\ \ * Unbatcher: readonly fields\ \ * fix: KcpServer.Stop now clears connections so they aren't carried ove…\ \ * fix: fixing use of new c# in 2020\ \ * feat: adding option to get Ip behind reverse proxy\ \ \ [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v79.0.0-2023-june-07)\ \ [v79.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v79.0.0)\ -- 2023-June-07\ \ \ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ \ * Added: Writer / Reader support for `DateTime` data type.\ \ * Added: `NetworkRoomManager` - `ReadyStatusChange` is now a virtual method.\ \ * Added: `NetworkTransform` interpolation can now be disabled for pos / rot / scale.\ \ * Added: `ExponentialMovingAverage` now has a `Reset` method.\ \ * Added: `NetworkClient`'s Snapshot Interpolation settings exposed in Network Manager.\ \ * Fixed: `NetworkBehaviour` SyncVar uses `netId` lookup.\ \ * Fixed: No longer use custom `NetworkBehaviour` writers for SyncVars.\ \ * Fixed: Writer for non-spawned `NetworkBehaviour` only writes 0 for `netId`.\ \ * Fixed: KCP updated to version 1.33.\ \ * Fixed: Simple Web Transport improved logging.\ \ * Fixed: `NetworkTime` - `PingWindowSize` shortened to 6 from 10 and use it in `ExponentialMovingAverage`.\ \ * Fixed: NetworkLoop no longer adds functions twice when Domain Reload is disabled.\ \ * Fixed: NetworkLoop no longer runs in edit mode.\ \ * Fixed: Network Messages now uses a static NetworkMessageId class and static ushort Id.\ \ * Fixed: Weaver now weaves in pre-computed function hash for RPCs.\ \ * Fixed: Snapshot Interpolation received various updates.\ \ * Fixed: NetworkTransform (Reliable) received various performance updates, fixed jitter.\ \ * Changed: Interest Management now derives from an abstract base class.\ \ * Changed: NetworkWriter - MaxStringLength changed to ushort.MaxValue.\ \ * **Breaking Changes:**\ \ * Removed obsolete OnServerError / OnClientError.\ \ * Removed old Unity 2018 / 2019\_3 compiler defines.\ \ * Remove NetworkClient.serverIp.\ \ * AsmDef files updated and simplified.\ \ \ \ [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v73.0.0-2023-feb-09)\ \ [v73.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v73.0.0)\ -- 2023-Feb-09\ \ \ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ \ * Added: `NetworkClient.OnGUI` now includes BTM for `bufferTimeMultiplier`.\ \ * Fixed: Client objects are now cleared before spawn handlers.\ \ * Fixed: `NetworkIdentity` doesn't reset `SyncObjects` anymore.\ \ * You can call the Reset method yourself on Sync\* collections.\ \ \ * Fixed: InitSyncObject IsWritable/IsRecording permissions fixed for host mode and other player's objects on client.\ \ * Fixed: Sync\* collections can now be modified before spawning again.\ \ * Fixed: Client Sync\* collections can be modified when offline now.\ \ * Fixed: Handlers are no longer double firing for Sync\* collections.\ \ * Fixed: SyncList handler for OP\_SET index parameter fixed.\ \ * Fixed: `SpawnObjects` now activates but does not spawn objects under inactive parents.\ \ * Fixed: `NetworkTransformBase` now checks for missing Main Camera in OnGUI.\ \ * Fixed: `NetworkTransformBase` now resets when changing authority in Client To Server mode.\ \ * Fixed: `NetworkTransformBase` OnClientAuthorityChanged is Server Only.\ \ * Fixed: `NetworkTransformReliable` now correctly uses `localScale` for syncing scale.\ \ * Fixed: `NetworkTransformReliable` now checks for changes after previous changes applied.\ \ * Fixed: Jitter from `NetworkTransformReliable` sending last known snapshot fixed.\ \ * Fixed: `NetworkServer.DisconnectAll` doesn't set active to false anymore...it just disconnects all connections.\ \ * `Shutdown` still properly cleans up all objects and sets active to false.\ \ \ * Fixed: Reset of statics in `NetworkClient` and `NetworkServer`.\ \ * Fixed: `ChangeOwner` message handler now adds / removes from client connection's `owned` HashSet.\ \ * Fixed: `NetworkClient` now sets `NetworkIdentity.connectionToServer` before `OnStartAuthority` / `OnStartClient` are called.\ \ * Fixed: `isClient` and `isOwned` are now properly set in `OnStartAuthority`.\ \ * Fixed: `isClient` and `isOwned` are now properly set when Interest Management is involved.\ \ * Fixed: KCP updated to version 1.29.\ \ * Fixed: OnClientDisconnect is now correctly invoked for DNS resolution failures.\ \ * Fixed: Removed invalid reference from KCP Assembly Definition file.\ \ * Fixed: Added SimpleWebTransport to Mirror.Transports Assembly Definition file.\ \ * Fixed: Most examples were reviewed and updated, improved PlayerController.\ \ * Fixed: Distance Interest Management now caches references to custom distance components.\ \ * Changed: `OnClientConnect` now fires as soon as authenticated, before any scene change.\ \ * Changed: Use GUID's enabled for all Assembly Definition files.\ \ * Changed: Network Manager HUD layout is now a bit wider for less wrapping.\ \ * Changed: OnGUI in Network Client is now public.\ \ * Changed: Compiler symbols have been culled to those covering the last 12 months and will continue to be culled to a rolling 12-month time period.\ \ * Changed: Latency Simulation Transport configuration has been revamped.\ \ * Breaking Change: Older obsoleted properties and methods have been removed.\ \ \ [Previous2024 Change Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2024-change-log)\ [Next2022 Change Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log)\ \ Last updated 1 year ago\ \ * [v86.13.4 -- 2023-Dec-24](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v86.13.4-2023-dec-24)\ \ * [v86.13.0 -- 2023-Dec-12](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v86.13.0-2023-dec-12)\ \ * [v81.4.0 -- 2023-Aug-03](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v81.4.0-2023-aug-03)\ \ * [v79.0.0 -- 2023-June-07](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v79.0.0-2023-june-07)\ \ * [v73.0.0 -- 2023-Feb-09](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log#v73.0.0-2023-feb-09) --- # CCU | Mirror A similar question came up on the [Unity forumsarrow-up-right](https://forum.unity.com/threads/stress-test-using-unity-as-server.1126640/#post-7245842) a while ago, so I'll copy my answer here in case it's useful to anyone else. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-McNCf_hQbEDISIAdzZM%252F-McNClIuZ7tf8G2tKAXB%252F2021-06-17_12-24-46%25402x.png%3Falt%3Dmedia%26token%3Dce81aec7-2762-4143-8161-1dee02f52374&width=768&dpr=3&quality=100&sign=3f4ae23f&sv=2) Our laggy 480 CCU test from 2019 One of the MMOs [made with Mirrorarrow-up-right](https://github.com/vis2k/Mirror#made-with-mirror) had quite a lot of CCU when it launched, I think it was Inferna. They split the map into separate server instances, with around 200 CCU limit per map. I would have to look it up again, but I believe they achieved around 1000 CCU per world this way at times. There's also a [very old videoarrow-up-right](https://www.youtube.com/watch?v=mDCNff1S9ZU&t=58s) of us trying 480 CCU worst case, all in one place like your video. It's laggy as hell, but the server survived just fine. Both Inferna and the 480 CCU video use old Mirror & Unity versions. We've had years of improvements since then, both for Mirror, Unity and server hardware. We still have plenty of optimizations to squeeze out of Mirror, with another CCU test planned afterwards around the end of this year. Keep in mind that your game's complexity is also a huge factor. A 3D physics movement MMO like WoW will be way harder to scale than a 2D click-to-move MMO. For an Indie developer, 2D is really worth considering. It's way cheaper, way easier to make and scales way better due to less complex physics/meshes etc. At the end of the day, there's definitely a limit to what we can achieve in MonoBehaviour world. For 1500 physics movement players like in WoW, you would definitely need DOTS or a server that does not run in Unity. Imho Unity & MonoBehaviour is still a good option. Better to **release** even a 500 CCU MMO with 250 CCU per instance, than **never release** a 1500 CCU MMO. [PreviousTCP and UDPchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp) [NextSyncDirectionchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/syncdirection) Last updated 4 years ago --- # KCP Transport | Mirror **KCP transport for Mirror.** kcp2k is the new default Transport for Mirror. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MejdokPOBSw8a_wSZel%252F-Mejek-K3_H83FB3r2Xr%252Fimage.png%3Falt%3Dmedia%26token%3D70b2d3e0-2df8-4357-a315-35bd3702de83&width=768&dpr=3&quality=100&sign=469a6f2c&sv=2) The KCP Transport component in the Inspector window ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport#about-this-transport) About this transport Why KCP: [https://github.com/skywind3000/kcp/blob/master/README.en.mdarrow-up-right](https://github.com/skywind3000/kcp/blob/master/README.en.md) * 100% C#. * Works on all platforms except WebGL. * Heavy test coverage (83.5%). * Extremely fast. * Extremely simple. * Nearly allocation free\*. "KCP is a fast and reliable protocol that can achieve the transmission effect of a reduction of the average latency by 30% to 40% and reduction of the maximum delay by a factor of three, at the cost of 10% to 20% more bandwidth wasted than TCP. It is implemented by using the pure algorithm, and is not responsible for the sending and receiving of the underlying protocol (such as UDP), requiring the users to define their own transmission mode for the underlying data packet, and provide it to KCP in the way of callback. Even the clock needs to be passed in from the outside, without any internal system calls." We are very excited about KCP and highly recommend trying it in your project. => Previously we had pure C# transports that were slow => And native C transports that were fast, but hard to maintain. KCP brings us the best of both worlds: it's as fast as our native C transports, while still being easy to maintain because it's 100% pure C#! ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport#usage) Usage Add the KCP Transport component to your NetworkManager. Unblock UDP (not TCP), Port 7777 (the default, unless you change it). ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport#credits) Credits skywind3000 for original kcp.c ([https://github.com/skywind3000/kcparrow-up-right](https://github.com/skywind3000/kcp) ) kcp-csharp for first C# port ([https://github.com/limpo1989/kcp-csharparrow-up-right](https://github.com/limpo1989/kcp-csharp) ) paul/lymdum/uwee for connection handling. [PreviousTransportschevron-left](https://mirror-networking.gitbook.io/docs/manual/transports) [NextTelepathy Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport) Last updated 3 years ago * [About this transport](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport#about-this-transport) * [Usage](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport#usage) * [Credits](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport#credits) --- # Telepathy Transport | Mirror Simple, message based, MMO Scale TCP networking in C#. And no magic. * Telepathy was designed with the [KISS Principlearrow-up-right](https://en.wikipedia.org/wiki/KISS_principle) in mind. * Telepathy is fast and extremely reliable, designed for [MMOarrow-up-right](https://assetstore.unity.com/packages/templates/systems/ummorpg-51212) scale Networking. * Telepathy uses framing, so anything sent will be received the same way. * Telepathy is raw C# and can be used in Unity3D too. * Telepathy is available on [GitHubarrow-up-right](https://github.com/vis2k/Telepathy) [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport#what-makes-telepathy-special) What makes Telepathy special? ---------------------------------------------------------------------------------------------------------------------------------------------------------- Telepathy was originally designed for [uMMORPGarrow-up-right](https://assetstore.unity.com/packages/templates/systems/ummorpg-51212) after 3 years in UDP hell. We needed a library that is: * Stable & Bug free: Telepathy uses only 400 lines of code. There is no magic. * High performance: Telepathy can handle thousands of connections and packages. * Concurrent: Telepathy uses one thread per connection. It can make heavy use of multi core processors. * Simple: Telepathy takes care of everything. All you need to do is call Connect/GetNextMessage/Disconnect. * Message based: if we send 10 and then 2 bytes, then the other end receives 10 and then 2 bytes, never 12 at once. MMORPGs are insanely difficult to make and we created Telepathy so that we would never have to worry about low level Networking again. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport#what-about) What about... ------------------------------------------------------------------------------------------------------------------------ * Async Sockets: didn't perform better in our benchmarks. * ConcurrentQueue: .NET 3.5 compatibility is important for Unity. Wasn't faster than our SafeQueue anyway. * UDP vs. TCP: Minecraft and World of Warcraft are two of the biggest multiplayer games of all time and they both use TCP networking. There is a reason for that. [PreviousKCP Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport) [NextWebSockets Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport) * [What makes Telepathy special?](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport#what-makes-telepathy-special) * [What about...](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport#what-about) --- # Integrations | Mirror Here we will maintain a list of assets known to be compatible with Mirror. If you know of others, please have the publisher contact us directly in our [Discordarrow-up-right](https://discord.gg/2BvnM4R) . ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/integrations#dissonance-voice-chat) [Dissonance Voice Chatarrow-up-right](https://assetstore.unity.com/packages/tools/audio/dissonance-voice-chat-70078) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Foq4V8yffvsFu7bYqQeGF%252Fimage.png%3Falt%3Dmedia%26token%3De9b30889-afd2-4e1e-95ac-4a177962a7df&width=768&dpr=3&quality=100&sign=94437c4f&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/integrations#steamworks-networking) [Steamworks Networkingarrow-up-right](https://assetstore.unity.com/packages/tools/integration/steamworks-v2-complete-190316) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FfRlsOfZ2VR4DJfEamGcl%252Fimage.png%3Falt%3Dmedia%26token%3D6bb0edbc-aef2-404e-b126-8ad06054dcfa&width=768&dpr=3&quality=100&sign=c364a46c&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/integrations#smoothsync) [SmoothSyncarrow-up-right](https://assetstore.unity.com/packages/tools/network/smooth-sync-96925) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FSnhxC58pVZuNG7RrE5qH%252Fimage.png%3Falt%3Dmedia%26token%3Db8473f1d-882b-49eb-a6c4-152ad5c559d6&width=768&dpr=3&quality=100&sign=9bb0e87&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/integrations#noble-connect-free) [Noble Connect Freearrow-up-right](https://assetstore.unity.com/packages/tools/network/noble-connect-free-141599) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FKD7UZgauSSYbB76FZOiz%252Fimage.png%3Falt%3Dmedia%26token%3D764cd35d-e478-4caa-b7d4-f1427cf55fe7&width=768&dpr=3&quality=100&sign=bfcd2296&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/integrations#weather-maker) [Weather Makerarrow-up-right](https://assetstore.unity.com/packages/tools/particles-effects/weather-maker-unity-weather-system-sky-water-volumetric-clouds-a-60955) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FMVSDCw8tNm1qc0IECeAO%252Fimage.png%3Falt%3Dmedia%26token%3D3a2b1730-cb4d-471e-a3d0-04a96bbf47df&width=768&dpr=3&quality=100&sign=7a7043f7&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/integrations#rts-engine) [RTS Enginearrow-up-right](https://assetstore.unity.com/packages/templates/packs/rts-engine-79732) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FRMKWkRD4Wz1hqpzgNJfp%252Fimage.png%3Falt%3Dmedia%26token%3D6245d271-1fbc-412c-84d7-b51880a74141&width=768&dpr=3&quality=100&sign=bd9f2751&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/integrations#master-audio-multiplayer) [Master Audio Multiplayerarrow-up-right](https://assetstore.unity.com/packages/tools/audio/master-audio-2022-aaa-sound-212962) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FGmLnJ8pZ35Xt3UMnzVJn%252Fimage.png%3Falt%3Dmedia%26token%3D5ebe493b-8c17-4781-9cf1-99e78a8de58e&width=768&dpr=3&quality=100&sign=a479af29&sv=2) [PreviousMigration Guidechevron-left](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide) [NextTimestamp Batchingchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/timestamp-batching) Last updated 3 years ago * [Dissonance Voice Chat](https://mirror-networking.gitbook.io/docs/manual/general/integrations#dissonance-voice-chat) * [Steamworks Networking](https://mirror-networking.gitbook.io/docs/manual/general/integrations#steamworks-networking) * [SmoothSync](https://mirror-networking.gitbook.io/docs/manual/general/integrations#smoothsync) * [Noble Connect Free](https://mirror-networking.gitbook.io/docs/manual/general/integrations#noble-connect-free) * [Weather Maker](https://mirror-networking.gitbook.io/docs/manual/general/integrations#weather-maker) * [RTS Engine](https://mirror-networking.gitbook.io/docs/manual/general/integrations#rts-engine) * [Master Audio Multiplayer](https://mirror-networking.gitbook.io/docs/manual/general/integrations#master-audio-multiplayer) --- # 2022 Change Log | Mirror circle-info Mirror is published to the [Asset Storearrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) at the start of every month, unless some critical issue causes a delay. circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v71.0.0-2022-dec-31) [v71.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v71.0.0) -- 2022-Dec-31 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: `NetworkClient.activeHost` added as static. * Added: Sync\* collections now support Client-to-Server Sync Direction. * Added: Network Manager HUD now has a StopClient button for Host mode. * This leaves the server running in Server Only mode and removes the host client. * Fixed: KCP updated to version 1.26. * Fixed: `NetworkManager.OnStopClient` now checks if client was started. * Fixed: `NetworkManager.OnClientSceneChanged` now checks for authenticated client before calling `NetworkClient.Ready`. * Fixed: `NetworkManager.mode` is now set to `offline` before calling OnStopClient to prevent a recursion. * Fixed: `SimpleWebSocket` logging improved. * Fixed: `NetworkManager` template now resets singleton in Awake override. * Fixed: `NetworkDiscovery` template now correctly has the messages defined as structs. * Fixed: NetworkTransform / NetworkTransformReliable now check for null connectionToClient in UpdateServer. * This cures the NRE's when player object is abandoned by scene changes. * Fixed: `NetworkTransformChild` `AddComponentMenu` attribute reset since it's obsolete. * Fixed: `NetworkRigidbody2D` now has `HelpURL` attribute. * Fixed: `NetworkServer` logs now have game object references for easier debugging. * Fixed: FPS script had wrong namespace. * Fixed: Network Authenticators now use `NetworkClient.Send` so we don't bypass a null check. * Fixed: `NetworkClient.owned` is now correctly cleaned up in OnDestroy. * Fixed: `NetworkIdentity.spawned` is now correctly cleaned up in OnDestroy. * Fixed: `SpawnObject` was missing a check for identities already spawned. * This cleans up the warnings in Additive Scenes implementations. * Changed: `NetworkServer.localConnection` is now `LocalConnectionToClient` type. * Changed: NetworkManager's OnStartServer and OnStartHost are now called later in the startup sequence. * Changed: `NetworkRoomManager` no longer does max connection checks...`NetworkServer` already does that sooner. * Obsolete: `NetworkServer.localClientActive` renamed to `activeHost`. * **BREAKING**: `NetworkTransform` and `NetworkTransformReliable` now inherit from a new `NetworkTransformBase`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v70.0.0-2022-dec-09) [v70.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v70.0.0) -- 2022-Dec-09 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Support for Unity 2019 LTS was restored * No promises as how long this will last. Unity no longer supports it, and code debt adds up. * Fixed: KCP updated to version 1.23. * Fixed: Examples have been updated to work with this release. * Fixed: Interest Management now uses `TryGetValue` in several places. * Fixed: Telepathy no longer calls OnDisconnected twice incorrectly. * Fixed: Transport handlers are cleared when NetworkClient restarts. * Fixed: Several errors with Multiplex Transport were fixed. * Fixed: Weaver now supports inheritance for `NetworkConnectionParameter`. * Fixed: Client-To-Server SyncVars weren't being sent to clients. * Fixed: Logging in transports was improved. * Changed: NetworkManager.OnClientDisconnect is now an empty virtual method. * Script Template also updated. * **Breaking**: `NetworkTransform` Reliable and Unreliable * Unreliable version replaces the old `NetworkTransform`. * `SyncInterval` is now managed by `NetworkServer` `sendRate` (set in Network Manager). * `NetworkTransformChild` removed...use Network Transform and set target to a child. * `clientAuthority` obsoleted in favor of `syncDirection` impemented in previous release. circle-info Support for Unity 2019 LTS was restored in this release, but we cannot promise how long we'll be able to maintain compatibility as code debt adds up. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v69.0.0-2022-nov-10) [v69.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v69.0.0) -- 2022-Nov-10 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- circle-info This version was published to the Asset Store as 2022-10. * Added: CCU Test example. * Added: `NetworkStatistics` component. * Fixed: `NetworkRigidbody` now uses double time to keep precision over long runtime. * Fixed: `NetworkLerpRigidbody` now uses double time to keep precision over long runtime. * Fixed: `NetworkWriter.WriteString()` now ensures capacity before writing. * Changed: Tools folder created and some rearrangement was done. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v68.0.0-2022-oct-21) [v68.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v68.0.0) -- 2022-Oct-21 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- circle-info This version was published to the Asset Store as 2022-09. * Added: Snapshot Interpolation example. * Added: `NetworkPingDisplay` now has configurable size. * Added: `NetworkManager.GetStartPosition` is now virtual so it can be overridden. * Added: Network Manager now has an Auto Connect option for headless clients / CCU testing. * Added: `NetworkConnection` now maintains `owned` HashSet on both server and client. * Added: `NetworkBehaviour` now has `SyncDirection` to make client authority components easier. * Note: This feature will continue to evolve and may change in future releases. * Fixed: Benchmark, Chat and Tanks examples were improved. * Fixed: Network Manager script template was updated. * Fixed: `NetworkBehaviour` logging was improved. * Fixed: `SimpleWebTransport` header lookup is now case-insensitive. * Fixed: Spatial Hash Interest Mgmt. now calculates visibility range correctly. * Fixed: Read/Write GUID no longer allocates garbage. * Fixed: Telepathy `ClientDisconnect` now calls `Disconnect` event correctly. * Fixed `NetworkServer.Spawn` now checks and warns for duplicates. * Fixed: `NetworkIdentity` now only checks `Application.isPlaying` in Editor context. * Fixed: Network Statistics properties made public so other components can access them. * Fixed: `InterestManagement.Awake` is now `protected virtual` so it can be overridden. * Fixed: `NetworkIdentity` serialization of `componentIndex` reduced to ~1 bit instead of 1 byte. * Fixed: `NetworkBehaviour` serialization of headers reduced to 1 byte instead of 4 bytes. * Fixed: `NetworkClient` now resets time interpolation whenever host connects or reconnects. * **Changed**: `NetworkBehaviour.ComponentIndex` reduced from `int` to `byte`. * **Changed**: Snapshot Interpolation refactored to version 2. * **Changed**: Latency Simulator `latencySpike` renamed to `jitter`. * **Changed**: Snapshot Interpolation split into time + value interpolation. * **Breaking**: Transports folder was moved up and various transports moved into that folder. * **Breaking**: Runtime folder renamed to Core. * **Breaking**: `NetworkIdentity` / `NetworkBehaviour` `OnSerialize` no longer returns a `bool`. * **Breaking**: `NetworkBehaviour.SerializeSyncVars` no longer returns a `bool`. * **Breaking**: `assetId` in `SpawnMessage` changed from `Guid` to `uint`. * **Breaking**: `OnError(Exception)` is now `OnError(TransportError, string)` where `TransportError` is an enum and string is free text provided by transports. * **Breaking**: `NTSnapshot` renamed to `TransformSnapshot` for clarity. * **Breaking**: `NetworkTime` was rewritten to use `NetworkClient`'s snapshot interpolation timeline. * **Obsolete**: `NetworkManager.serverTickRate` renamed to `sendRate`. * **Obsolete**: `NetworkManager.serverTickinterval` was moved to `NetworkServer`. * **Obsolete**: `NetworkTransport.activeTransport` renamed to `active`. * **Obsolete**: `NetworkBehavior.hasAuthority` renamed to **isOwned** for clarity. * **Obsolete**: `NetworkConnection.clientOwnedObjects` renamed to `owned` for clarity. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v67.1.0-2022-may-05) [v67.1.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v67.1.0) -- 2022-May-05 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: KCP updated to version 1.19. * Fixed: Team Interest Mgmt `OnDestroyed` logic was improved. * Fixed: Comments in various Network Authenticators were updated. * Fixed: Benchmark example was improved so movement revolves around origin. * Fixed: Cmd/Rpc bandwidth reduced from 4 bytes to 2. * Fixed: `Texture2D` now includes dimensions and reads `Color32` correctly and supports nulls. * Fixed: `NetworkServer.SendToObservers` now correctly uses `NetworkConnectionToClient`. * Fixed: `NetworkClient` now checks and warns for duplicate scene ID. * **Changed**: `NetworkClient` / `NetworkServer` `OnError` renamed to `OnTransportError` for clarity. * **Breaking**: Obsoletes were removed. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v66.0.9-2022-apr-17) [v66.0.9arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v66.0.9) -- 2022-Apr-17 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- circle-exclamation **NOTE:** This was to be the last Mirror release to support Unity 2019 LTS, as it has reached end of life by Unity. Support was restored in Mirror 70.0.0 above. * Added: [Network Statistics](https://mirror-networking.gitbook.io/docs/manual/components/network-statistics) component, showing messages & packets sent & received per second. * Added: `Queue.TryDequeue` extension added for Unity 2019 & 2020 compatibility. * Fixed: `NetworkClient.ChangeOwner` now uses `isLocalPlayer` flag to check if `OnStopLocalPlayer` should be called. * Fixed: `ReadNetworkBehavior` now correctly reads data on client even if the associate `NetworkIdentity` is missing from the client. * Fixed: `NetworkClient.SpawnPrefab` now correctly looks for custom spawn handlers before using registered prefabs list instead of after. * Fixed: `NetworkWriterExtensions` now uses `WriteArray` instead of `Write`. * Fixed: Attempting to serialize prefabs and not-spawned game objects throws a more obvious exception. * Fixed: `DestroyAllClientObjects` now also resets after unspawn handler called. * Fixed: Calling `StopClient` in Host mode no longer resets `nextNetId`. * Fixed: Calling `StopClient` in Host mode no longer destroys objects on clients. * Fixed: It should now be possible to call StopClient in Host mode to leave the server in a running "Server Only" state, keeping all clients connected and running normally. * Fixed: `AggressiveInlining` attribute added in many places to improve performance. * **Changed:** `NetworkWriter` / `NetworkReader` API simplified. * **Changed:** `PooledNetworkReader` / `PooledNetworkWriter` renamed to `NetworkReaderPooled` / `NetworkWriterPooled`. * **Changed:** Transport base class moved to Runtime folder, Transport folder renamed to Transports [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v65.0.0-2022-mar-09) [v65.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v65.0.0) -- 2022-Mar-09 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Command / ClientRpc / TargetRpc can now be overloaded. * Added: Network Behaviour now has `OnStopLocalPlayer` virtual method, invoked right before `OnStopClient`. Script Template has also been updated. * Added: Network Manager Template overrides `singleton` to eliminate the need to cast Network Manager's singleton to derived class type. * Added: Support for generic `NetworkBehaviour` subclasses. * Fixed: Network Reader/Writer uses blittable reads/writes where possible. * Fixed: Android compatibility for Read/Write blittable. * Fixed: Android Multicast Discovery. * Fixed: `NetworkTransformChild` now correctly syncs initial state when spawned. * Fixed: Latency Simulation now uses `Time.unscaledTime`. * Fixed: `SimpleWebsocketTransport` has been updated to fix a number of bugs, including compatibility with Unity 2021.x, and handling of messages larger than 64K. * **Changed**: A bunch of virtual methods now take `NetworkConnectionToClient` instead of `NetworkConnection`. * **Changed**: `RemoteCallHelper` renamed to `RemoteProcedureCalls`. * **Changed**: `CmdDelegate` renamed to `RemoteCallDelegate`. * **Changed**: `MirrorInvokeType` renamed to `RemoteCallType`. * **Changed:** `NetworkManager.clientLoadedScene` is now `protected`. * **Obsolete**: `NetworkTransform` now has overloads for `CmdTeleport` / `RpcTeleport` with Quaternion rotation, deprecating separate `CmdTeleportAndRotate` / `RpcTeleportAndRotate` methods, made possible by implementing Command / ClientRpc overloads mentioned above. * **Obsolete:** Experimental Network Transform components. Use the regular ones instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v57.0.0-2022-jan-12) [v57.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v57.0.0) -- 2022-Jan-12 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: KCP updated to version 1.17. * Fixed: Use Read/Write blittable for performance improvement. * **Removed**: Obsolete Network Visibility. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v55.3.8-2022-jan-05) [v55.3.8arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v55.3.8) -- 2022-Jan-05 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: [Team Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/team) and Network Team components. * Added: [Device Authenticator](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators/device-authenticator) . * Added: Custom Interest Management [Script Template](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) . * Added: Custom Network Transform [Script Template](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) . * Added: Rotation parameter added to `NetworkTransform` `CmdTeleport` / `RpcTeleport`. * Added: Support for a bunch more nullable types. * Added: [Additive Levels](https://mirror-networking.gitbook.io/docs/manual/examples/additive-levels) example. * Added: Texture2D and Sprite are now supported [Data Types](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) . * Fixed: Fast Enter Play mode without Reload Domain now supported by resetting all statics. * Fixed: Network Transform now uses less bandwidth by only syncing changes based on sensitivity. * Fixed: KCP updated to version 1.15. * Fixed: `ReplacePlayerForConnection` now correctly updates `isLocalPlayer` flag. * Fixed: `OnStopClient` no longer called twice in certain cases. * Fixed: `NetworkServer` now checks for `active` before invoking Interest Management updates. * Fixed: Objects spawned with a client owner no longer lose ownership when respawned via interest management. * Fixed: Delayed Disconnect in Basic Authenticator now uses `HashSet` of connections pending disconnect. * Fixed: `NetworkTransform` now checks for ready client before sending updates to server. * Fixed: `OnStartLocalPlayer` now correctly called again after `RemovePlayerForConnection` followed by `AddPlayerForConnection` with the same player object. * Changed: `NetworkMatch` moved to `InterestManagement/Match` folder. * Changed: Internal code for `SyncVar`. Resetting non-default inspector values may be required. * Changed: Tanks example updated. * Changed: Chat example updated...overhauled really. * Changed: Network Reader / Writer now use blittable serialization where possible (4-6x performance improvement). * **Breaking**: Removed obsolete `ConfigureServerFrameRate` Use `ConfigureHeadlessFrameRate` instead. * **Breaking**: Removed obsolete `PersistNetworkManagerToOfflineScene`. * **Breaking**: `NetworkAuthenticator` `OnClientAuthenticated` event no longer needs a NetworkConnection parameter. * **Obsolete**: OnClient\* virtual methods in Network Manager no longer take a `NetworkConnection` parameter. * **Obsolete**: Network Room Manager client overrides no longer have `NetworkConnection` parameter. Use `NetworkClient.connection` in your overrides instead. [Previous2023 Change Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2023-change-log) [Next2021 Change Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log) Last updated 1 year ago * [v71.0.0 -- 2022-Dec-31](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v71.0.0-2022-dec-31) * [v70.0.0 -- 2022-Dec-09](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v70.0.0-2022-dec-09) * [v69.0.0 -- 2022-Nov-10](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v69.0.0-2022-nov-10) * [v68.0.0 -- 2022-Oct-21](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v68.0.0-2022-oct-21) * [v67.1.0 -- 2022-May-05](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v67.1.0-2022-may-05) * [v66.0.9 -- 2022-Apr-17](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v66.0.9-2022-apr-17) * [v65.0.0 -- 2022-Mar-09](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v65.0.0-2022-mar-09) * [v57.0.0 -- 2022-Jan-12](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v57.0.0-2022-jan-12) * [v55.3.8 -- 2022-Jan-05](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log#v55.3.8-2022-jan-05) --- # Timestamp Batching | Mirror Let's learn how Mirror sends around messages. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/timestamp-batching#batching) 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_ [_MTU_arrow-up-right](https://en.wikipedia.org/wiki/Maximum_transmission_unit) _)_. 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. circle-check In short, batching significantly reduces bandwidth and improves performance. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/timestamp-batching#timestamps) 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: Copy [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`. circle-info **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. [PreviousIntegrationschevron-left](https://mirror-networking.gitbook.io/docs/manual/general/integrations) [NextTCP and UDPchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp) Last updated 4 years ago * [Batching](https://mirror-networking.gitbook.io/docs/manual/general/timestamp-batching#batching) * [Timestamps](https://mirror-networking.gitbook.io/docs/manual/general/timestamp-batching#timestamps) --- # Latency Simulation Transport | Mirror Mirror's Latency Simulation transport allows you to test your project under non-ideal network conditions. Add it to NetworkManager, **wrap** it around your regular Transport, drag it into NetworkManager.transport. It can simulate: * Latency in milliseconds * Packet loss in % * Packet scramble / reorder circle-info Reliable messages are ordered and guaranteed delivery by definition. Packet loss / scramble over reliable manifests itself via latency. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MVkvmuS0mbMGgI3J5MV%252F-MVkw6s6rfAFfLDQ-RWv%252F2021-03-14_21-32-23%25402x.png%3Falt%3Dmedia%26token%3Dea633fd5-8097-4c96-ab18-e9c883a0ea6b&width=768&dpr=3&quality=100&sign=129a5700&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F57072365%2F225437999-0667da1b-abf7-49c5-8c1d-d1a2fec36b12.jpg&width=768&dpr=3&quality=100&sign=10eddbb0&sv=2) NMLatencySim [PreviousMultiplex Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/multiplex-transport) [NextIgnorancechevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance) Last updated 2 years ago --- # Migration Guide | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#migrating-a-project-from-unet-hlapi) Migrating a project from UNet (HLAPI) ------------------------------------------------------------------------------------------------------------------------------------------------------------------ This guide gives you a step by step instruction for migrating your project from UNET to Mirror. Mirror is a fork of UNET. As such the migration is straight forward for most projects. You should review the information on the [Deprecations](https://mirror-networking.gitbook.io/docs/manual/general/deprecations) page to see if your project will be impacted. There's also a [Migration Toolarrow-up-right](https://github.com/Lymdun/MirrorConverter/) you can try. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-1-backup) 1\. BACKUP You have been warned. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-2-install-mirror-and-restart-unity) 2\. Install Mirror and Restart Unity Get Mirror from the [Asset Storearrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) and import it in your project. Alternatively you can grab the latest [releasearrow-up-right](https://github.com/vis2k/Mirror/releases) from GitHub if you're feeling adventurous, but be aware that bleeding edge dev releases are not necessarily stable. **NOTE:** You must restart Unity after adding Mirror to the project for the components menu to update correctly. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-3-replace-namespace) 3\. Replace namespace Replace `UnityEngine.Networking` for `Mirror` everywhere in your project. For example, if you have this: Copy using UnityEngine.Networking; public class Player : NetworkBehaviour { ... } replace it with: At this point, you might get some compilation errors. Don't panic, these are easy to fix. Keep going... ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-4-replace-playercontroller-with-identity) 4\. Replace playerController with identity Replace references to `NetworkConnection.playerController` with `NetworkConnection.identity`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-5-remove-networksettings) 5\. Remove NetworkSettings NetworkSettings in UNet have channels, but this is flat out broken. Rather than ignoring your settings we removed channels from NetworkSettings completely. `sendInterval` is now set in code and / or the inspector too. For example, if you have this code: replace it with: Please note that the default transport [Telepathyarrow-up-right](https://mirror-networking.com/docs/Articles/Transports/Telepathy.html) , completely ignores channels, all messages are reliable, sequenced and fragmented. They just work with no fuss. If you want to take advantage of unreliable channels try a UDP or Steam [transport](https://mirror-networking.gitbook.io/docs/manual/transports) instead. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-6-change-syncliststruct-to-synclist) 6\. Change SyncListStruct to SyncList There is a bug in the original UNet Weaver that makes it mess with our `Mirror.SyncListStruct` without checking the namespace. In Mirror, we fixed SyncLists so that they work with structs by default. For example, if you have definitions like: replace them with: ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-7-replace-networkhash128-and-networkinstanceid) 7\. Replace NetworkHash128 and NetworkInstanceId These have been changed to System.Guid and uint, respectively. For example, if you have something like this: replace with: ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-8-update-your-synclist-callbacks) 8\. Update your SyncList callbacks In UNet, SyncLists have a callback delegate that gets called in the client whenever the list is updated. We have changed the callback to be a C# event instead and we also pass the item that was updated/removed. For example, if you have this code: replace it with: Notice the callback will also work in the server in Mirror. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-9-replace-components) 9\. Replace Components Every networked prefab and scene object needs to be adjusted. They will be using `NetworkIdentity` from Unet, and you need to replace that component with `NetworkIdentity` from Mirror. You may be using other network components, such as `NetworkAnimator` or `NetworkTransform`. All components from Unet should be replaced with their corresponding component from Mirror. Note that if you remove and add a NetworkIdentity, you will need to reassign it in any component that was referencing it. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-10-update-extended-components) 10\. Update Extended Components Some commonly extended components, such as NetworkManager, have changed method parameters in Mirror. A commonly used override is OnServerAddPlayer. Using the original HLAPI, your override may have looked like this: In your newly Mirror-capable NetworkManager, if you are using the `OnServerAddPlayer` override, remove the "playerControllerId" and "extraMessageReader" parameters from your override and the base call: See Custom [Player Spawn Guide](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning) for details on how to submit custom characters now. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-11-pick-your-transport) 11\. Pick your transport You can choose one of several transports in Mirror. Open your NetworkManager gameobject, in the inspector you will see a `TelepathyTransport` component by default. Drag in one of the available transports and remove `TelepathyTransport` if you wish to use a UDP based transport instead. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-12-configure-address-and-port) 12\. Configure address and port In HLAPI, you configure the port and local address in the NetworkManager. One of our goals is to make Mirror transport independent. Not all transports need address and port. Some transports might even use more than one port at the same time, so these settings were inadequate. We removed the port and address and all other Network Info properties from NetworkManager, and we moved them to the transport components instead. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-13-update-your-firewall-and-router) 13\. Update your firewall and router LLAPI uses UDP. Mirror uses TCP by default. This means you may need to change your router port forwarding and firewall rules in your machine to expose the TCP port instead of UDP. This highly depends on your router and operating system. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#video-version) Video version -------------------------------------------------------------------------------------------------------------------- See for yourself how uMMORPG was migrated to Mirror: [http://www.youtube.com/watch?v=LF9rTSS3rlIarrow-up-right](http://www.youtube.com/watch?v=LF9rTSS3rlI) [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#possible-error-messages) Possible Error Messages ---------------------------------------------------------------------------------------------------------------------------------------- * TypeLoadException: A type load exception has occurred. - happens if you still have SyncListStruct instead of SyncListSTRUCT in your project. * NullPointerException: The most likely cause is that you replaced NetworkIdentities or other components but you had them assigned somewhere. Reassign those references. * `error CS0246: The type or namespace name 'UnityWebRequest' could not be found. Are you missing 'UnityEngine.Networking' using directive?` Add this to the top of your script: `UnityWebRequest` is not part of UNet or Mirror, but it is in the same namespace as UNet. Changing the namespace to Mirror caused your script not to find UnityWebRequest. The same applies for `WWW` and all `UnityWebRequest` related classes. [PreviousDeprecationschevron-left](https://mirror-networking.gitbook.io/docs/manual/general/deprecations) [NextIntegrationschevron-right](https://mirror-networking.gitbook.io/docs/manual/general/integrations) Last updated 5 years ago * [Migrating a project from UNet (HLAPI)](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#migrating-a-project-from-unet-hlapi) * [1\. BACKUP](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-1-backup) * [2\. Install Mirror and Restart Unity](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-2-install-mirror-and-restart-unity) * [3\. Replace namespace](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-3-replace-namespace) * [4\. Replace playerController with identity](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-4-replace-playercontroller-with-identity) * [5\. Remove NetworkSettings](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-5-remove-networksettings) * [6\. Change SyncListStruct to SyncList](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-6-change-syncliststruct-to-synclist) * [7\. Replace NetworkHash128 and NetworkInstanceId](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-7-replace-networkhash128-and-networkinstanceid) * [8\. Update your SyncList callbacks](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-8-update-your-synclist-callbacks) * [9\. Replace Components](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-9-replace-components) * [10\. Update Extended Components](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-10-update-extended-components) * [11\. Pick your transport](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-11-pick-your-transport) * [12\. Configure address and port](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-12-configure-address-and-port) * [13\. Update your firewall and router](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#id-13-update-your-firewall-and-router) * [Video version](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#video-version) * [Possible Error Messages](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide#possible-error-messages) Copy using Mirror; public class Player : NetworkBehaviour { ... } Copy [NetworkSettings(channel=1,sendInterval=0.05f)] public class NetStreamer : NetworkBehaviour { ... } Copy public class NetStreamer : NetworkBehaviour { void Start() { syncInterval = 0.05f; } } Copy public class SyncListQuest : SyncListStruct {} Copy public class SyncListQuest : SyncList {} Copy public sealed class SpawnItemMessage : MessageBase { public NetworkHash128 assetID; public NetworkInstanceId networkInstanceID; public Vector3 position; public Quaternion rotation; } Copy public sealed struct SpawnItemMessage : NetworkMessage { public System.Guid assetID; public uint networkInstanceID; public Vector3 position; public Quaternion rotation; } Copy using UnityEngine; using UnityEngine.Networking; public class MyBehaviour : NetworkBehaviour { public SyncListInt m_ints = new SyncListInt(); private void OnIntChanged(SyncListInt.Operation op, int index) { Debug.Log("list changed " + op); } public override void OnStartClient() { m_ints.Callback = OnIntChanged; } } Copy using UnityEngine; using Mirror; public class MyBehaviour : NetworkBehaviour { public SyncListInt m_ints = new SyncListInt(); private void OnIntChanged(SyncListInt.Operation op, int index, int oldItem, int newItem) { Debug.Log("list changed " + op + " old item: " + item + " new item: " + newItem); } public override void OnStartClient() { m_ints.Callback += OnIntChanged; } } Copy public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader) { base.OnServerAddPlayer(conn, playerControllerId, extraMessageReader); // your code } Copy public override void OnServerAddPlayer(NetworkConnection conn) { base.OnServerAddPlayer(conn); // your code } Copy using UnityWebRequest = UnityEngine.Networking.UnityWebRequest; --- # History Bounds | Mirror In the previous chapter, we discussed how to use lag compensation to check player's hitboxes in the past. To minimize performance overhead, it can be useful to first cast against `HistoryBounds` before we decide which players to rollback. are essentially a 4-dimensional bounding box: (x,y,z,time). In other words, a bounding box which contains all the player's positions in the last second or so. The orange Collider shows the Tank's red Collider over the last second. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/history-bounds#usage-guide) Usage guide: * Attach the `HistoryCollider` component to your NetworkIdentity * Make sure your NetworkIdentity has a collider, drag it into the component's `actualCollider` field * Add a child GameObject with a BoxCollider and isTrigger enabled. Drag it into the component's `boundsCollider`. * Press play, enable Gizmos, notice the orange HistoryCollider. * The component automatically adjusts the child trigger collider to match the orange box, which means that you can use Physics.Raycast against all the history colliders very easily. In other words: if a player fires a gun, do this: * Raycast against all HistoryColliders to find out which other player's we need to check * Then apply lag compensation for the collider's parent NetworkIdentity * Then check if it was hit circle-info This is a brief overview on why HistoryCollider exists, and how to use it. In the future we will provide a proper FPS demo with all the advanced techniques. [PreviousClient Side Predictionchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction) [NextTestschevron-right](https://mirror-networking.gitbook.io/docs/manual/general/tests) Last updated 2 years ago --- # SyncDirection | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FBuOyIJsbzmYfatKQsfg7%252F2022-10-18%2520-%2520SyncDirection.png%3Falt%3Dmedia%26token%3D86db4af0-6bea-424f-a3f7-1dd5066c8818&width=300&dpr=3&quality=100&sign=1d6b9a0&sv=2) We have recently added the new **SyncDirection** feature, so here is a quick overview. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/syncdirection#why-syncdirection) Why SyncDirection Usually, data is synced from server to client in OnSerialize. However, some components like NetworkTransform need to be able to sync from client to server, in case of client authority movement. Previously, we had to use \[Command\]s in order to sync client authoritative NetworkTransform data to the server, since OnSerialize would only go from server to client. This has several downsides: * It's a lot of extra code to have both OnSerialize and manual remote calls * It's extra Bandwidth: every Command includes a function hash, etc. * Intervals need to be implemented manually, since syncInterval is only for OnSerialize. As you can see, it would be great if there was an option for OnSerialize to go from client to server as well. circle-info Note that ClientToServer is a bit of a simplification. Technically it goes from the owner client, to the server, where it's then broadcast to all the other observer clients which aren't owners. _In case of client authoritative NetworkTransform, it means your local movement is sent to the server, which then broadcasts it to the other players so they see you move as well._ Long story short, we have fully implemented SyncDirection for client authority components. To summarize: * **ServerToClient** is the default. **OnSerialize** (and all SyncVars, SyncLists) are sent from server to client every syncInterval. **OnDeserialize** is called on the client. * **ClientToServer** is for client authoritative components. **OnSerialize** is called on the owner client every **syncInterval**. It's then send to the server, where **OnDeserialize** is called. Afterwards the server broadcasts to all other clients except the owner. **OnDeserialize** is then called on those other clients. Note that ClientToServer data could still be verified in OnDeserialize on the server. That's why it's technically not 'client authority', hence the name SyncDirection. For example, while the owner client may sync NetworkTransform data to the server, you could still validate every move in the server's OnDeserialize before applying & broadcasting it. [PreviousCCUchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/ccu) [NextRound Trip Time (RTT)chevron-right](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt) Last updated 3 years ago --- # Reverse Proxy | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FeBXSHBTOF2FzKDtO1CKy%252Fimage.png%3Falt%3Dmedia%26token%3D65e5c2a5-a1de-41d0-8723-2ad36cdca5e1&width=768&dpr=3&quality=100&sign=61532470&sv=2) WebGL with Reverse Proxy - 500 CCU Using a reverse proxy performs better than doing SSL encryption within Unity as part of the game server process: * Unity is single-threaded, while the reverse proxy is a separate process that's generally engineered to enterprise class performance and is multi-threaded. * Encryption is computationally expensive, so better to not bog down Unity with that workload. * Unity / mono may not be up to date on TLS version or be able to read the latest certificates. This section has instructions for both [Linux](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/reverse-proxy/linux) and [Windows](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/reverse-proxy/windows) . [PreviousWebSockets Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport) [NextWindowschevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/reverse-proxy/windows) Last updated 2 years ago --- # Edgegap Transports | Mirror [Edgegap's Distributed Relayarrow-up-right](https://edgegap.com/en/platform/distributed-relay) Service offers relays in their many locations all over the world, allowing for player hosted games without having to worry about NAT or latency issues. In order to use the relay service, you will need to either [set up your own backend to start relay sessions on-demandarrow-up-right](https://docs.edgegap.com/docs/relay-edgegap-api) or you can use Edgegap's [Server Browserarrow-up-right](https://docs.edgegap.com/learn/server-browser) or [Matchmaker arrow-up-right](https://docs.edgegap.com/docs/matchmaking) service to do this for you (and as an added bonus you get lobbies or matchmaking on-top). Mirror offers the following transports to interact with the relay service: * [Edgegap Relay](https://mirror-networking.gitbook.io/docs/manual/transports/edgegap-transports/edgegap-relay) : Barebones relay transport using KCP [PreviousEncryption Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport) [NextEdgegap Relaychevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/edgegap-transports/edgegap-relay) Last updated 1 month ago --- # Edgegap Relay | Mirror The `EdgegapKcpTransport` is a bare-bones transport using [KCP](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport) through Edgegap's distributed relay. It expects you to set up the relay session and communicate the details with all players yourself. Once you have done so, set the `relayAdddress`, `sessionId`, `userId` and the respective `relayGameClientPort` or `relayGameServerPort` depending on if the player is hosting or not. All that is left, once the details are filled in, is to start the Client/Server/Host as usual via the NetworkManager instance. [PreviousEdgegap Transportschevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/edgegap-transports) [NextComponentschevron-right](https://mirror-networking.gitbook.io/docs/manual/components) Last updated 2 years ago --- # NetGraph | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FAh6szUpWCpKputmdogkp%252FScreenshot%25202024-09-10%2520at%252015.31.35.png%3Falt%3Dmedia%26token%3D1f14cf44-2aad-40c6-9947-19ae65ae1c8e&width=768&dpr=3&quality=100&sign=8795ef48&sv=2) Image preview of netgraph on a connected client. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/netgraph#how-to-use) How to use: -------------------------------------------------------------------------------------------------------- 1. Locate prefab - Mirror/Components/Profiling/Prefabs/GraphCanvas 2. Drag prefab into scene, and setup toggle key to activate. (or hook upto your own canvas UI buttons if desired.) 3. Start editor, press your hotkey, play game, see stats in realtime. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FdJPg4xjuYNPyfanToWVQ%252FScreenshot%25202024-09-10%2520at%252015.40.07.png%3Falt%3Dmedia%26token%3Db80d2151-2d00-44ad-b156-b0c8ccfe05c0&width=768&dpr=3&quality=100&sign=4a3f40a5&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FRv6cdVv81JDr2bzgWnbR%252FScreenshot%25202024-09-10%2520at%252015.35.45.png%3Falt%3Dmedia%26token%3D3f141d40-f46a-4cbd-8d39-e8aa0cab8d06&width=768&dpr=3&quality=100&sign=425f3b9f&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FrJlqwy07hAXKN31ZVXo6%252FScreenshot%25202024-09-10%2520at%252015.31.09.png%3Falt%3Dmedia%26token%3D4efcd6b5-8251-4254-9c2b-3720b683f2ca&width=768&dpr=3&quality=100&sign=fc0e49bf&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/netgraph#customisability) Customisability: ------------------------------------------------------------------------------------------------------------------ You can drag individual graph prefabs into your existing game canvas's, and adjust their UI and variables to your liking. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FDxtWbbTIxiT8WCRYbi5k%252FScreenshot%25202024-09-10%2520at%252018.13.42.png%3Falt%3Dmedia%26token%3D32357fa5-455f-41b2-a422-758482c39152&width=768&dpr=3&quality=100&sign=1c54fedb&sv=2) [PreviousTestschevron-left](https://mirror-networking.gitbook.io/docs/manual/general/tests) [NextFAQchevron-right](https://mirror-networking.gitbook.io/docs/manual/faq) Last updated 1 year ago * [How to use:](https://mirror-networking.gitbook.io/docs/manual/general/netgraph#how-to-use) * [Customisability:](https://mirror-networking.gitbook.io/docs/manual/general/netgraph#customisability) --- # Multiplex Transport | Mirror The Multiplex Transport is not a transport itself, but it allows you to combine other transports so that your clients can connect to your servers via either one of them. A common use case for the Multiplex Transport is a server listening for both WebGL and mobile / desktop clients. Your WebGL clients can connect to the server using a [Websocket Transport](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport) and your mobile or desktop clients can connect to the same server via TCP or UDP transports. You can configure any number of transports in the Multiplex Transport. To use the Multiplex Transport follow these steps: 1. Add a game object with a Network Manager to your scene if you have not done so 2. By default, Mirror will add KCP Transport to your Network Manager game object 3. Add a Multiplex Transport component to the game object 4. Assign the Multiplex Transport component in your Network Manager's transport field 5. Add a Websocket Transport component to the game object 6. Add the KCP Transport component to the Multiplex Transport as the first transport 7. Add the Websocket Transport component to the Multiplex Transport as the second transport Please note that KCP and Websocket Transport cannot listen to the same port. By default KCP listens to 7777 (UDP) and the websocket transport listens to 7778 (TCP). If you build your game as a WebGL game, the KCP Transport will be skipped and your client will use the websocket transport. If you build your game as a mobile or desktop app, it will choose KCP Transport. The server will happily accept connections from both. Here is what the configuration should look like: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FxfasOm2bvUfZ36gH1Smv%252Fimage.png%3Falt%3Dmedia%26token%3Dbc8a6fdf-07b1-4f47-9e31-762bcdfbb548&width=768&dpr=3&quality=100&sign=c2e185fb&sv=2) [PreviousSSLchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl) [NextLatency Simulation Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/latency-simulaton-transport) Last updated 2 years ago --- # FizzySteamworks Transport | Mirror FizzySteamworks is a Steam P2P transport for Mirror, it utilizes Steam's P2P service to directly connect or relay your connection to another player. FizzySteamworks is based on the [Steamworks.Netarrow-up-right](https://github.com/rlabrecque/Steamworks.NET) wrapper. You can get the release [**Here**arrow-up-right](https://github.com/Chykary/FizzySteamworks/releases) with the latest version of Steamworks.Net included or you can clone the repo [**Here**arrow-up-right](https://github.com/Chykary/FizzySteamworks) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/fizzysteamworks-transport#features) Features ----------------------------------------------------------------------------------------------------------------------- * Multiple Customizable Channels : You can customize the channels in the transport, whether you want just 1 or 5 channels that are unreliable or reliable (best to leave channel 0 as reliable). * Steam Nat Punching & Relay : The transport will use Steam to do Nat Punching to your destination, and if that doesn't work, steam's relay Server will be used to ensure you can always connect (latency may vary). * No Code Changes Needed : If you Already use Mirror, you just need to slap this transport in (maybe add your steam App ID in your build), and everything should work the same like any other Mirror Transport. "It Just Works" -Todd Howard ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNi0dXI-TZcXrbyqUo%252F-MUNi7sIbqsolwCvJb6R%252Fimage.png%3Falt%3Dmedia%26token%3De1c4445c-5ef1-4a24-ab00-7011208b935a&width=768&dpr=3&quality=100&sign=aebdb5a8&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/fizzysteamworks-transport#credits) Credits --------------------------------------------------------------------------------------------------------------------- * [Fizz Cubearrow-up-right](https://github.com/FizzCube) : Original author for this Transport. * [Chykaryarrow-up-right](https://github.com/Chykary/FizzySteamworks) : The current maintainer for this Transport. * [rlabrecquearrow-up-right](https://github.com/rlabrecque) : Creator of Steamworks.Net. * [vis2karrow-up-right](https://github.com/vis2k) : Creator of Mirror. * Valve : Steam [PreviousLiteNetLib Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport) [NextFizzyFacepunch Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/fizzyfacepunch-transport) Last updated 5 years ago * [Features](https://mirror-networking.gitbook.io/docs/manual/transports/fizzysteamworks-transport#features) * [Credits](https://mirror-networking.gitbook.io/docs/manual/transports/fizzysteamworks-transport#credits) --- # Tests | Mirror A lot of developers are surprised by how stable Mirror is, compared to what they've used before. This is not by coincidence. Mirror is **heavily** tested with: * \> **1400** unit tests * ~ **80%** test coverage ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-McNKDzdVpiWkUi3AfO3%252F-McNLt7D7WVo6LT8tKru%252F2021-06-17%2520-%252079%252C6%2520percent%2520-%2520including%2520obsoletes.png%3Falt%3Dmedia%26token%3D9ffc1ed5-cc04-4396-8cef-04f8fe517eb1&width=768&dpr=3&quality=100&sign=260a1311&sv=2) \[2021-06-17\] Mirror Test Coverage of 79.6% - including all \[Obsoletes\] circle-check As far as we know, **Mirror** has the highest test coverage of any `MonoBehaviour`networking library for **Unity**. In other words, 80% of our code is **covered with tests** making sure that for the given input, it always produces the correct output. Here is what this means in practice: * If you **report a bug**, we usually fix it and add a test to guarantee that it **never** happens again. If we **accidentally** introduce a bug, odds are our tests will catch it immediately before you ever encounter it in our game. * We can **improve** existing functions with confidence. If a rewrite doesn't produce exactly the same output as the previous version, then our tests will catch it. circle-check As **rule** **of** **thumb**, encountering a Mirror bug in production simply means that we haven't covered that part of the code with tests yet. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-Ma7nUr0ZLTvEjVVnPKl%252F-Ma7o48WN0C1t_Id8USK%252F2021-05-20_16-06-57%25402x.png%3Falt%3Dmedia%26token%3D25adcd7a-52ed-43f0-88bf-710b938d654e&width=768&dpr=3&quality=100&sign=1a87669c&sv=2) If you download Mirror from the **Asset Store**, then you don't see those tests because we don't want you to worry about them. They are only on **GitHub**. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tests#code-coverage-settings) Code Coverage Settings ---------------------------------------------------------------------------------------------------------------------------- To reproduce the Coverage results, use Unity's Code Coverage Package and run all of our Edit Mode tests. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-McNIDlulb5k-CJLsfQd%252F-McNIaclZb5da0cAYSrH%252F_SETTINGS_.png%3Falt%3Dmedia%26token%3D39676fd5-736e-497b-8b4d-bef7e45fcb88&width=768&dpr=3&quality=100&sign=ea554953&sv=2) Code Coverage settings [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tests#mirrortest) MirrorTest ---------------------------------------------------------------------------------------------------- If you want to contribute tests or clean up existing ones, please do! Check out the `MirrorEditModeTest` and `MirrorPlayModeTest` base classes. They provide some convenience functions and setup that we use for most of our tests. For example, Creating a networked object with some network components. [PreviousHistory Boundschevron-left](https://mirror-networking.gitbook.io/docs/manual/general/history-bounds) [NextNetGraphchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/netgraph) Last updated 4 years ago * [Code Coverage Settings](https://mirror-networking.gitbook.io/docs/manual/general/tests#code-coverage-settings) * [MirrorTest](https://mirror-networking.gitbook.io/docs/manual/general/tests#mirrortest) --- # WebSockets Transport | Mirror A Mirror transport that uses the [websocket protocolarrow-up-right](https://en.wikipedia.org/wiki/WebSocket) , thus enabling multiplayer in the browser from Unity WebGL builds! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fgit-blob-f3246bff04213588f69fea2ebd2223fa5aa30c66%252Fsimple-web-transport-current-inspector-view.png%3Falt%3Dmedia&width=768&dpr=3&quality=100&sign=751a3357&sv=2) Simple Web Transport Inspector [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#ssl-settings) SSL Settings -------------------------------------------------------------------------------------------------------------------------- SSL settings is obsolete and may be removed in a future release. circle-info NOTE: WebGL performs a lot better with a Reverse Proxy, and that's generally easier to set up and maintain than using cert.json and PFX files. Go to the [Reverse Proxy](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/reverse-proxy) page for instructions. For legacy purposes, you can read more about simple web transport and SSL in this [SSL guide](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#server-settings) Server Settings -------------------------------------------------------------------------------------------------------------------------------- Specify what port the websocket based game server listens on. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#client-settings) Client Settings -------------------------------------------------------------------------------------------------------------------------------- These settings allow for users to customize web game client behavior. For example, you may want to introduce a reverse proxy server, and you want to configure the web game clients to connect to the reverse proxy server instead of the game server directly. These settings enable you to do that. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#logging) Logging ---------------------------------------------------------------------------------------------------------------- Supported log levels: * `None` * `Error` * `Warn` (default) * `Info` * `Verbose` * `Flood` Log levels can be set using the dropdown on the transport or setting `Mirror.SimpleWeb.Log.level` in code directly. For debugging purposes, it is encouraged to set the log level to `Verbose` (or `Flood` in extreme cases). For normal use `Info` or `Warn` is recommended. Setting the log level to `None` will disable logging completely. Use this option with extreme caution. circle-info The transport applies the dropdown value in its `Awake` and `OnValidate` methods. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#log-methods) Log methods Log methods in this transport use [ConditionalAttributearrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute?view=netstandard-2.0) , so they are removed depending on the preprocessor defines. This preprocessor symbol effects the logging: * `DEBUG` allows warn/error logs. See the [Unity docsarrow-up-right](https://docs.unity3d.com/Manual/PlatformDependentCompilation.html) on how to set custom preprocessor defines. [PreviousTelepathy Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport) [NextReverse Proxychevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/reverse-proxy) Last updated 2 years ago * [SSL Settings](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#ssl-settings) * [Server Settings](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#server-settings) * [Client Settings](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#client-settings) * [Logging](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport#logging) --- # Round Trip Time (RTT) | Mirror ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#undefined) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#understanding-rtt) Understanding RTT circle-info **Round Trip Time (rtt)** is the time it takes for a message to go to the other end and back. RTT always depends on two factors: 1. **Latency:** Network Message take some time to travel over the internet. 2. **Update Interval:** Messages need to be processed and sent back to the other end. If your server's update rate is slow, RTT will be large. Mirror calculates round trip time on the client, and on the server: * Clients can find it in `NetworkTime.rtt` * Servers can find it in each `NetworkServer.connection.rtt` (different for each connection) If you want to display **rtt** in your game, you can use our `NetworkPingDisplay` component. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#local-machine-rtt) Local Machine RTT If you run our Tanks demo with a server and a client on the same computer, you'll see an average rtt of around 8 ms: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F7inOkJVL3kSGpIdb0mhr%252F2023-07-18%2520-%2520rtt%25208ms.png%3Falt%3Dmedia%26token%3Df47fd8be-60b1-41e4-a484-0b23b981152e&width=768&dpr=3&quality=100&sign=e1e65eff&sv=2) 60 Hz update rate gives 8 ms RTT This may seem strange at first: while 8 ms isn't much, it's still not as low as you would expect on your local computer. Clearly packets won't need 8 ms to travel through your memory. The reason for this is simple: by default, Mirror's NetworkManager.sendInterval is set to 60 Hz. This means that network updates happen every 16 milliseconds (1 second / 60). RTT messages may arrive during an update, or while waiting 16 ms for the next update. On average, this means that there are 8 milliseconds of wait time for each RTT message. Which is why the above picture shows an RTT of about 8 ms on your local machine. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#optimizing-rtt) Optimizing RTT A send interval of 60 Hz is a reasonable tradeoff between bandwidth (the more often you send, the larger your bandwidth costs) and RTT. If you want to trade more bandwidth for lower RTT: * Increase sendInterval to 120 Hz or more * Make sure that VSYNC is disabled (if your screen is running at 60 Hz, Vsync will cap your update rate to 60 Hz) * Make sure your game runs fast enough (if your CPU is too slow to achieve 120 Hz, then your send rate obviously can't be 120 Hz) With an extreme send rate and frame rate, we can easily get the Tanks demo's RTT down to 1-2ms on our local machine. Of course, this isn't recommended in a production game: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FPUk9UG0uvEJsL5Hf0M97%252F2023-07-18%2520-%2520rtt%25202ms.png%3Falt%3Dmedia%26token%3Da90f2877-4923-4e52-ad7e-89811af6f386&width=768&dpr=3&quality=100&sign=ed9a16cb&sv=2) [PreviousSyncDirectionchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/syncdirection) [NextConnection Qualitychevron-right](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality) Last updated 2 years ago * [](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#undefined) * [Understanding RTT](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#understanding-rtt) * [Local Machine RTT](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#local-machine-rtt) * [Optimizing RTT](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt#optimizing-rtt) --- # FizzyFacepunch Transport | Mirror FizzyFacepunch is a Steam P2P transport for Mirror, it utilizes Steam's P2P service to directly connect or relay your connection to another player. FizzyFacepunch is based on the [Facepunch.Steamworksarrow-up-right](https://github.com/Facepunch/Facepunch.Steamworks) wrapper. You can get the release [**Here**arrow-up-right](https://github.com/Chykary/FizzyFacepunch/releases) or you can clone the repo [**Here**arrow-up-right](https://github.com/Chykary/FizzyFacepunch) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/fizzyfacepunch-transport#features) Features ---------------------------------------------------------------------------------------------------------------------- * Multiple Customizable Channels : You can customize the channels in the transport, whether you want just 1 or 5 channels that are unreliable or reliable (best to leave channel 0 as reliable). * Steam Nat Punching & Relay : The transport will use Steam to do Nat Punching to your destination, and if that doesn't work, steam's relay Server will be used to ensure you can always connect (latency may vary). * No Code Changes Needed : If you Already use Mirror, you just need to slap this transport in (maybe add your steam App ID in your build), and everything should work the same like any other Mirror Transport. "It Just Works" -Todd Howard ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNiC7KQZeq4HQl0baS%252F-MUNiF_7TGsJWRYTt7BN%252Fimage.png%3Falt%3Dmedia%26token%3De41a3dd8-ae57-4e82-8eb6-0f02f6526397&width=768&dpr=3&quality=100&sign=2608e6ec&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/fizzyfacepunch-transport#credits) Credits -------------------------------------------------------------------------------------------------------------------- * [Chykaryarrow-up-right](https://github.com/Chykary/FizzyFacepunch) : The author of this Transport. * [Facepuncharrow-up-right](https://github.com/Facepunch) : Creator of Facepunch.Steamworks. * [vis2karrow-up-right](https://github.com/vis2k) : Creator of Mirror. * Valve : Steam [PreviousFizzySteamworks Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/fizzysteamworks-transport) [NextEncryption Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport) Last updated 5 years ago * [Features](https://mirror-networking.gitbook.io/docs/manual/transports/fizzyfacepunch-transport#features) * [Credits](https://mirror-networking.gitbook.io/docs/manual/transports/fizzyfacepunch-transport#credits) --- # Connection Quality | Mirror Mirror does a lot of work to smooth out poor network connections. However, there's only so much we can do on. circle-exclamation For poor connections, it's best practice to display a '**Poor Connection**' warning. Mirror's ConnectionQuality consists of three parts to make this very easy for your game. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality#connectionquality.cs) **ConnectionQuality.cs** Standalone connection quality enum & heuristics, which can be used outside of Unity if needed. Mirror provides the following connection quality levels: Copy public enum ConnectionQuality : byte { EXCELLENT, // ideal experience for high level competitors GOOD, // very playable for everyone but high level competitors FAIR, // very noticeable latency, not very enjoyable anymore POOR, // unplayable ESTIMATING, // still estimating } Currently it offers two heuristics: * **Simple** (based on Ping & Jitter) * **Pragmatic** (based on Snapshot Interpolation). ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality#networkpingdisplay) NetworkPingDisplay This component can be added to the NetworkManager to display a Ping & Connection Quality indicator on the bottom right of the screen. Feel free to modify this to your needs, or create your own. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FnzuStGrxDZwIp0IeHOcq%252F2023-06-25%2520-%2520connection%2520quality%252C%2520gui%252C%2520callback.png%3Falt%3Dmedia%26token%3De3768cd5-59d4-4ee7-8309-8aff67ad94ca&width=768&dpr=3&quality=100&sign=8020b8a7&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality#networkmanager-callbacks) **NetworkManager Callbacks** * **CalculateConnectionQuality()** can be overwritten to inject your own heuristic. By default, it uses the **Simple** heuristic from above. This is called every **connectionQualityInterval** seconds, which can also be configured in the NetworkManager. * **OnConnectionQualityChanged**() can be used to show warnings to the user. By default, this emits a log message - useful for debugging user logs, etc. [PreviousRound Trip Time (RTT)chevron-left](https://mirror-networking.gitbook.io/docs/manual/general/round-trip-time-rtt) [NextLag Compensationchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation) Last updated 2 years ago * [ConnectionQuality.cs](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality#connectionquality.cs) * [NetworkPingDisplay](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality#networkpingdisplay) * [NetworkManager Callbacks](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality#networkmanager-callbacks) Copy protected virtual void CalculateConnectionQuality() { NetworkClient.connectionQuality = ConnectionQualityHeuristics.Simple( NetworkTime.rtt, NetworkTime.rttVar ); } Copy protected virtual void OnConnectionQualityChanged(ConnectionQuality previous, ConnectionQuality current) { Debug.Log($"[Mirror] Connection Quality changed from {previous} to {current}"); } --- # 2021 Change Log | Mirror circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v53.0.0-2021-oct-20) [v53.0.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v53.0.0) -- 2021-Oct-20 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: `ChangeOwnerMessage`. `NetworkIdentity.AssignClientAuthority` and `RemoveClientAuthority` now send this message instead of a `SpawnMessage`, so transform data is no longer reset to server values, so no more snap-back of moving objects. * Added: `SyncDictionary` can now be declared and initialized from an existing List. * Added: Nullable color added to Data Types Mirror handles. * Added: `ILPostProcessor` is now used for Unity versions 2020.3 and later. * Fixed: Stopping Discovery no longer causes a crash. * Fixed: Additive Scenes example had misplaced scene objects. * Fixed: `NetworkManager.ServerChangeScene` now aborts if scene change already in progress. * Fixed: `hasAuthority` is now properly cleared on client when unspawning scene objects. * Fixed: Match Interest Management now correctly handles networked objects without `NetworkMatch` components, and no longer throws Key not found exception in certain cases. * Fixed: `NetworkManager.StopClient` no longer fires twice in certain cases. * Fixed: `NetworkMatch` was missing attributes. * Changed: `NetworkLoop` static class is now public. * Changed: `NetworkConnection.observing` is now public. Changed: `NetworkTransformV2` default values updated. `interpolateScale` also defaults to `false` now. * Changed: `NetworkTransformV2` `isClientAuthority` now `protected` instead of `private`. * Changed: Examples using `NetworkTransformV2` now using default values. * Changed: Updated `NetworkManager` Script Template. * Changed: Tanks example has health bars now. * Changed: `componentIndex` is now a `byte` in `CmdMessage` and `RpcMessage` structs. * Changed: `SyncObject` is now a class instead of an interface. * **Obsolete**: `SyncObject.Flush` - Use `ClearChanges` instead. * **Obsolete**: `NetworkBehaviour.getSyncVarHookGuard` - Use `GetSyncVarHookGuard` instead. * **Obsolete**: `NetworkBehaviour.setSyncVarHookGuard` - Use `SetSyncVarHookGuard` instead. * **Obsolete**: `NetworkBehaviour.SetDirtyBit` - Use `SetSyncVarDirtyBit` instead. * **Obsolete**: `NetworkServer.SendToReady` - Use `SendToReadyObservers` instead. * **Removed**: Various obsolete methods that were at least 3 months old. * **Removed**: Fallback transport -- no longer included or supported. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v46.0.4-2021-sep-03) [v46.0.4arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v46.0.4) - 2021-Sep-03 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ * Added: Tanks example now has `GUIConsole` for easier debugging. * Fixed: `UnpackAndInvoke` now throws error and disconnects in case of missing handlers. * Fixed: `NetworkServer`/`NetworkClient` now detects ever-growing batches. * Fixed: Weaver now uses `ILPostProcessing` in Unity 2020+. * Fixed: Movement delay in `NetworkTransformV2`. * Fixed: `NetworkTransformBase.OnDrawGizmos` now only runs in play mode. * Fixed: Added missing `using` to Network Manager template. * Fixed: Some `OnGUI` calls are now wrapped in `#if UNITY_EDITOR || DEVELOPMENT_BUILD`. * Changed: `NetworkEarlyUpdate`/`NetworkLateUpdate` in `NetworkLoop` now exposed via Action events. * Changed: Multiple Matches example now uses Match Interest Management. * Changed: Multiple Additive Scenes example now uses Scene Interest Management. * **Obsolete**: `NetworkIdentity.spawned` has been split into `NetworkServer.spawned` and `NetworkClient.spawned`. * **Removed**: Network Observer template. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v44.0.2-2021-aug-08) [v44.0.2arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v44.0.2) -- 2021-Aug-08 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Scene Interest Management. Put this on Network Manager and remove all Network Scene Checker components. * Added: Match Interest Management. Put this on Network Manager and replace Network Match Checker with new Network Match component. * Added: Interest Management now has `OnSpawned` / `OnDestroyed` events. * Added: Network Transform V2 with Snapshot Interpolation. * Added: Network Transport exception events that transports can raise to Network Manager's `OnServerError` and `OnClientError` overrides. Transports still need to implement their part. * Added: `ZigZag VarInt` added back to Compression module. * Fixed: Network Discovery HUD now calls `StopDiscovery` when stopping server/host/client. * Fixed: `NetworkTime.lastPingTime` is now reset properly. * Fixed: KCP updated to version 1.12. * Fixed: `NetworkBehaviour` dirty check uses double time. * Fixed: `NetworkTime.UpdateClient` uses double precision time for accuracy over days/weeks. * Fixed: `NetworkAnimator` uses double precision time for accuracy over days/weeks * Fixed: Quaternion Compression would produce wrong result for certain values. * Fixed: Added missing `[Command]` attribute to `NetworkAnimator.CmdSetAnimatorSpeed`. * Fixed: `DestroyObject` is now called when cleaning up scene identities too. Sends unspawn messages and calls `OnStopClient`/`OnStopServer`properly. * Fixed: Clear `hasAuthority` when destroying and call `OnStopAuthority`. * Changed: Distance Interest Management now has custom range component, replacing Network Proximity Checker. * Changed: Per-scene interest management replaces Network Scene Checker. * Changed: Network Match component separated from Network Match Checker. * Changed: Match Interest Management replaces Network Match Checker. * Changed: `NetworkManager.isNetworkActive` is now a readonly bool. * Changed: `NetworkManager.ConfigureServerFrameRate` renamed to `ConfigureHeadlessFrameRate`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v42.2.12-2021-jul-12) [v42.2.12arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v42.2.12) -- 2021-Jul-12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Timestamp-based batching. Batching is always on now and is bidirectional. * Added: `NetworkServer` / `NetworkClient` `OnConnected` / `OnDisconnected` events now public so custom Network Managers can hook into them. * Fixed: `NetworkServer` / `NetworkClient` `Shutdown` now correctly clears `OnConnected` / `OnDisconnected` event handlers. * Fixed: Scene loading with batching works now. * Fixed: KCP 1.11 significantly reduced garbage allocations. * Fixed: Fallback Transport didn't propagate Early/Late Update. * Fixed: `OnClientDisconnect` wasn't being called for host client. * Fixed: Interest Management V2 now allows `SetHostVisibility` overwriting. * Fixed: Serialization precision over days using frame count instead of single precision time. * Fixed: Added null check and error logging when `networkBehaviours` array is null. * Fixed: Force calling `NetworkIdentity.Awake` when parent is inactive. * Fixed: `OnClientChangeScene` was not firing for host client. * Fixed: Avoid NRE in `UnpackAndInvoke`. * Fixed: Null handling in `WriteUri` and `ReadUri`. * Fixed: `FinishLoadScene` should not be called when `customHandling` is true (Additive Scenes). * Fixed: Prevent assetId from being set to an empty string. * Fixed: `clientAuthority` is now public in `NetworkRigidbody` / `NetworkRigidbody2D`. * Changed: Transports are no longer paused (disabled) during scene loading. Message processor handles this correctly now, so transports can be simplified. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v40.0.9-2021-jun-08) [v40.0.9arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v40.0.9) -- 2021-Jun-08 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: `ServerAuthFailed` bool to Basic Authenticator. * Added: Discovery HUD now has a Stop Button. * Fixed: KCP updated to version 1.10. * Fixed: Telepathy updated to version 1.8. * Fixed: `NetworkIdentity` default script execution order set to -1. * Fixed: Discovery now properly shuts down in `OnDisable` / `OnDestroy`. * Fixed: Discovery now stops discovering when client is connected to game server. * Fixed: `NetworkTransform` sync scale and interpolation. * Fixed: Player object now prevented from being added to Network Manager's spawnable prefabs list * Fixed: Simple Web Sockets transport SSL Handshake. * Fixed: `NetworkServer.OnDisconnect` now calls `DestroyPlayerForConnection` if `NetworkManager` doesn't handle it. * Fixed: `NetworkClient.Disconnect` now checks for null connection and that it's not called twice. * Fixed: `NetworkTime` now resets when server starts. * Fixed: Basic example `PlayerUI` text corrected. * Fixed: Timeouts in Telepathy fixed. * Fixed: Observers are now correctly cleared after other clients disconnect. * Changed: `NetworkConnection` parameter removed from Network Authenticator's Client messages. * Changed: `MessagePacking GetId` return value changed to `ushort`. * Changed: `Transport.ServerDisconnect` return is now void instead of bool. * Removed: Network Manager's Idle Timeout. * Removed: Cloud API and examples. * **Obsolete**: Fallback Transport will be removed in a later release. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v35.1.0-2021-mar-29) [v35.1.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v35.1.0) -- 2021-Mar-29 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Network Discovery now has a bool to disable automatic active discovery. * Added: `PersistNetworkManagerToOfflineScene` to Network Manager...see tooltip. * Added: Latency Simulation Transport that can be added to Network Manager and have normal transport chained to it to simulate network latency. * Added: Sync Mode tooltip. * Added: Headless clients now set `targetFramerate` like headless servers * Added: `NetworkTransform` now has the following features: * Compress Rotation option * Sync Scale option * Interpolate Scale option * Fixed: No Writer found / No Reader found errors have been resolved. * **NOTE:** You may need to delete your `Library/ScriptAssemblies` folder and IL2CPP cache * Fixed: `NetworkIdentity.isLocalPlayer` is only set, but never reset. Fixes a bug where `isLocalPlayer` would be false in `OnDestroy`, so some components couldn't rely on it in `OnDestroy`. * Fixed: `NetworkIdentity.Reset` now resets `isLocalPlayer` _after_ the `isLocalPlayer` /`ClearLocalPlayer` check. * Fixed: `NetworkIdentity.OnDestroy` now only clears `NetworkClient.localPlayer` if we are still the local player. * Fixed: Client Shutdown is no longer run twice via user code calling `StopClient`. * Fixed: `SyncVar` field label not shown in Unity 2020 versions (Unity bug). * Changed: Network Manager `OnServerAddPlayer` now adds the connection id to the object name (on the server only, not synced to clients). * Changed: Several fields in `NetworkTime` were renamed. The previous field names are still there and **obsolete** and will be removed in a later version. * Changed: Most of `ClientScene` is now **obsolete**, use same or similar properties in `NetworkClient` instead. `ClientScene` will be fully deprecated and removed in a later version. * Changed: `NetworkClient.RegisterHandler` overload that included a `NetworkConnection` is now **obsolete** and will be removed in a later version. Handlers can use `NetworkClient.connection` directly. * Changed: Channel constants names were shortened. The original constants are still there and **obsolete**, and will be removed in a later version. * **Breaking**: Minimum supported Unity version is now 2019.4.x LTS. * **Breaking**: `ClientScene.onLocalPlayerChanged` removed. * **Breaking**: Compiler symbols culled to Mirror 17 and later versions. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v32.1.4-2021-mar-08) [v32.1.4arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v32.1.4) -- 2021-Mar-08 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: `NetworkIdentity` now has `isServer` / `isClientOnly`. * Added: Global Interest Management. This may eventually lead to replacement of Scene Checker, Match Checker, and Owner Checker components. * Added: GUI Console ported from uMMORPG (F12 to show/hide). * Added: Network Manager now takes itself out of DDOL in `StopServer` / `StopClient` when offline scene is defined to avoid singleton collision. * Added: Message batching. Enable in Network Manager. * Added: Custom Player Loop: * `NetworkEarlyUpdate` (before any Update/FixedUpdate) * `NetworkLateUpdate` (after any Update/FixedUpdate/LateUpdate) loops * Added: KCP Tick split into `TickIncoming` / `TickOutgoing` to utilize the new NetworkEarly/LateUpdate functions...minimizes latency. * Added: Push > Pull Broadcasting Part 1. * Fixed: Telepathy 1.7 receive timeout disabled by default, increased `MirrorTransport` timeout to 30sec from 5sec to cover scene changes. * Fixed: `NetworkServer.SpawnObserversForConnection` refactored to support all visibility cases (`ForceShown` / `ForceHidden` / `Default`) and all systems (legacy / new / default). * Fixed: `NetworkManager.StopServer/StopClient`: avoid `NullReferenceException` when called in `OnApplicationQuit` or from tests. * Fixed: `NetworkServer.Update`: inactive connection check moved into the main connections `foreach` loop. Eliminates a `foreach`\-connections loop. * Fixed: `NetworkServer.Update`: separate connections update loop moved into the main loop. Now there is only one connections loop. * Changed: `NetworkManagerHUD.showGUI` is now obsolete and will be removed in a later version. * Changed: `SendToClientOfPlayer` is now obsolete and will be removed in a later version. * **Breaking**: `LogFactory` and logging asset feature removed. * **Breaking**: Command `ignoreAuthority` parameter renamed to `requiresAuthority`, default true. * **Breaking**: `ClientRpc` `excludeOwner` parameter renamed to `includeOwner`, default true. * **Breaking**: `ClientScene.spawnableObjects` is no longer public. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#version-3053----2021-feb-15) [v30.5.3arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v30.5.3) -- 2021-Feb-15 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: Fixed a bug in batching for messages larger than MTU. * Fixed: Telepathy 1.6 fixes data races and improves stability. * Fixed: KCP 1.8 fixes empty message sending / receiving undefined behaviour and fixes IPv6 on Nintendo Switch. * Changed: Network Manager default max connections is now 100. * **Breaking**: `NetworkServer` / `NetworkClient` don't use Connect/Disconnect messages any more. Connect/Disconnect events are raised by the transport instead. * **Breaking**: `OnServerError` / `OnClientError` removed since no transport ever implemented them. * **Breaking** Removed `NetworkConnection.InvokeHandler` as no longer needed. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#version-3050----2021-feb-05) [v30.5.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v30.5.0) -- 2021-Feb-05 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: [KCP Transportarrow-up-right](https://mirror-networking.com/docs/Articles/Transports/KCPTransport.html) updated to version 1.7. * Added: Batching support for server messages - See Network Manager to enable. * Added: [Network Owner Checkerarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkOwnerChecker.html) . * Added: [Script Templatesarrow-up-right](https://mirror-networking.com/docs/Articles/General/ScriptTemplates.html) are back in the package -- See the new Mirror section in the Assets > Create menu. * Added: Unreliable channel added to KCP Transport. * Fixed: Performance improvements to KCP Transport. * Fixed: Examples with UI now work with Unity 2018.4 again * Fixed: `NetworkServer.OnConnected` allows for `connectionId` < 0 now. * Fixed: Corrected `NetworkRoomPlayer` `ReadyStateChanged` `oldReadyState` parameter name. * Changed: Ping/Pong messages now use unreliable channel if available from transports. * **Breaking** Read / Write Blittable has been removed. [Previous2022 Change Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2022-change-log) [Next2020 Change Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log) Last updated 1 year ago * [v53.0.0 -- 2021-Oct-20](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v53.0.0-2021-oct-20) * [v46.0.4 - 2021-Sep-03](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v46.0.4-2021-sep-03) * [v44.0.2 -- 2021-Aug-08](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v44.0.2-2021-aug-08) * [v42.2.12 -- 2021-Jul-12](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v42.2.12-2021-jul-12) * [v40.0.9 -- 2021-Jun-08](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v40.0.9-2021-jun-08) * [v35.1.0 -- 2021-Mar-29](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v35.1.0-2021-mar-29) * [v32.1.4 -- 2021-Mar-08](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#v32.1.4-2021-mar-08) * [v30.5.3 -- 2021-Feb-15](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#version-3053----2021-feb-15) * [v30.5.0 -- 2021-Feb-05](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log#version-3050----2021-feb-05) --- # LiteNetLib Transport | Mirror **LiteNetLib based transport for Mirror.** [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#usage) Usage ------------------------------------------------------------------------------------------------------------ 1. Download the unity package from [Releases arrow-up-right](https://github.com/MirrorNetworking/LiteNetLibTransport/releases) and import it to your project (it does not contain Mirror) 2. Put `LiteNetLibTransport` component on gameobject with NetworkManager and assign it there [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#features) Features ------------------------------------------------------------------------------------------------------------------ * UDP * Built-in Network Discovery and UPnP * Fully managed code * Small CPU and RAM usage * Small packet size overhead ( 1 byte for unreliable, 3 bytes for reliable packets ) * Different send mechanics * Reliable with order * Reliable without order * Ordered but unreliable with duplication prevention * Simple UDP packets without order and reliability * Automatic small packets merging * Automatic fragmentation of reliable packets * Automatic MTU detection * NTP time requests * Packet loss and latency simulation * IPv6 support (dual mode) * Connection statisitcs (need DEBUG or STATS\_ENABLED flag) * Multicasting (for discovering hosts in local network) [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#il2cpp-warning) IL2CPP Warning! ------------------------------------------------------------------------------------------------------------------------------- With IL2CPP, IPv6 is only supported on Unity 2018.3.6f1 and later because of this: [Unity ChangeLogarrow-up-right](https://unity3d.com/unity/whats-new/2018.3.6) > IL2CPP: Added protocol support for IPv6 on Windows. (1099133) > > IL2CPP: Correctly indicate that IPv6 is not supported on non-IPv6 platforms. (1108823) Also, socket Reuse Address option isn't available in IL2CPP. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#credits) Credits ---------------------------------------------------------------------------------------------------------------- RevenantX - for [LiteNetLibarrow-up-right](https://github.com/RevenantX/LiteNetLib/releases) vis2k & Paul - for [Mirrorarrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) Coburn - for [Ignorancearrow-up-right](https://github.com/SoftwareGuy/Ignorance) which i've used as an example Dankrushen - for helping me find one small mistake which i couldn't find for two days Lucas Ontivero - for [Open.Natarrow-up-right](https://github.com/lontivero/Open.NAT/releases) , used for UPnP shiena - for NetworkDiscoveryHUD [PreviousIgnorancechevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance) [NextFizzySteamworks Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/fizzysteamworks-transport) Last updated 4 years ago * [Usage](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#usage) * [Features](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#features) * [IL2CPP Warning!](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#il2cpp-warning) * [Credits](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport#credits) --- # TCP and UDP | Mirror TCP and UDP are both protocols used to send information over the internet - in fact, they are the two most commonly used internet protocols in the world: TCP was developed in the 1970s, while UDP was introduced in the 1980s. However, it is important to note two key differences between TCP and UDP communications: * TCP has built-in reliability, ensuring data gets from A to B correctly with a higher latency trade-off. * UDP has lower latency with it's data transfer, but the raw protocol is unreliable by nature and makes no assurances data will be sent from A to B correctly. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#tcp-transmission-control-protocol) [TCP (Transmission Control Protocol)arrow-up-right](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- As stated before, TCP is the most popular protocols on the internet. TCP is used for HTTP, SSH, FTP, and many more applications. TCP core features make it easy for programers to work with the protocol, since a programmer will be able to assure data will be sent from A to B correctly. However, while this sounds great, it can introduce higher latency when connections are malfunctioning or experiencing severe turbulence. In a game environment, TCP is better for slower paced games where latency isn't important but the game data is. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#key-features-include) Key features include * **Reliable:** Applications don't have to worry about missing packets. If a packet gets lost, TCP will resend it. All data is either transmitted successfully or you get an error and the connection is closed. * **Sequenced:** TCP guarantees that every message will arrive in the same order it was sent. If you send "a" then "b" you will receive "a" then "b" on the other side as well. * **Connection oriented:** TCP has the concept of a connection. A connection will stay open until either the client or server decides to close it. Both the client and server get notified when the connection ends. * **Congestion control:** If a server is being overwhelmed, TCP will throttle the data to avoid congestion collapse. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#transports) Transports using the TCP protocol * [Telepathy](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport) * [WebSockets](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport) [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#udp-user-datagram-protocol) [UDP (User Datagram Protocol)arrow-up-right](https://en.wikipedia.org/wiki/User_Datagram_Protocol) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- UDP is used for real time applications such as fast paced action games or Voice over IP (VoIP), where low latency is more important than reliability. Application examples include Skype, Discord, Zoom and many others. In a game environment, the raw power of UDP can be harnessed to allow for a greater control of how data is being sent, allowing non-critical data to be sent faster. This in turn makes UDP better for fast paced games where latency between server and client is important and if a few packets are lost, the game can recover. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#key-features-include-1) Key features include * **Low Latency:** UDP is faster because it doesn't need to wait for the remote side to acknowledge packets. Instead, it can send keep sending new data packets one after the other. It is also known as a "scattershot" protocol, since it'll just shoot data at clients with no assurances that they'll actually get the data. * **Channel support:** Channels allow for different delivery types. Depending on the implementation, one channel can be used for critical data that needs to get to the destination, while a different channel can be used for "send and forget" data transfer without any reliability. * **Different packet types:** Depending on the implementation on top of the UDP protocol, some transports offer different packet sending methods, such as Reliable Ordered, Reliable Unordered, Unreliable, and more depending on the implementation. Reliable UDP transfer depends on the implementation, but it is usually modelled after TCP's reliability system. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#transports-1) Transports using the UDP Protocol * [Ignorance](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance) * [KCP](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport) * [LiteNetLib](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport) [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#the-choice-is-yours) The choice is yours ---------------------------------------------------------------------------------------------------------------------------- Mirror is transport independent, they can simply by added to your NetworkManager GameObject. Mirror comes with a [KCP](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport) transport _(all platforms except WebGL)_ and a [Websocket](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport) _(WebGL)_ transport by default. See the [Transports](https://mirror-networking.gitbook.io/docs/manual/transports) page for more about transports. Pick whatever transport works best for you and your game. We recommend you profile your game's networking and collect real world numbers before you make a final decision. [PreviousTimestamp Batchingchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/timestamp-batching) [NextCCUchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/ccu) Last updated 4 years ago * [TCP (Transmission Control Protocol)](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#tcp-transmission-control-protocol) * [Key features include](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#key-features-include) * [Transports using the TCP protocol](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#transports) * [UDP (User Datagram Protocol)](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#udp-user-datagram-protocol) * [Key features include](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#key-features-include-1) * [Transports using the UDP Protocol](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#transports-1) * [The choice is yours](https://mirror-networking.gitbook.io/docs/manual/general/tcp-and-udp#the-choice-is-yours) --- # Encryption Transport | Mirror The Encryption Transport is not a transport itself, but it allows you to encrypt the data flowing through an existing transport. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#technical-details) Technical details The transport does an asymmetric key exchange via [ECDHarrow-up-right](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman) and [HKDFarrow-up-right](https://en.wikipedia.org/wiki/HKDF) \-SHA256 to safely derive a common 256-bit symmetric key, which is then used for [AESarrow-up-right](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) \-[GCMarrow-up-right](https://en.wikipedia.org/wiki/Galois/Counter_Mode) with a 96-bit nonce and 128-bit mac ([similarly used for TLS 1.3arrow-up-right](https://en.wikipedia.org/wiki/Transport_Layer_Security#Cipher) ). AES-GCM secures the data in-flight and checks the integrity on the receiving end with the help of the mac (a "checksum" of sorts) The handshake process is entirely via unreliable and encryption is order/reliability agnostic, so will work with all kinds of transports. Once the handshake is complete, the connection is entirely secure. For complete [Man-In-The-Middlearrow-up-right](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) security, at least one side needs to validate the public key (usually the client validates the server key). ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#usage) Usage In order to use the transport, assuming you have a transport set up already, you simply add the transport to the "Inner" field and assign the EncryptionTransport to your NetworkManager ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FjmI63ZpCMa6oPZuYM5it%252Fimage.png%3Falt%3Dmedia%26token%3D0ad788da-aae8-4a54-a49d-a25b4ab89fc1&width=768&dpr=3&quality=100&sign=15a778c5&sv=2) Basic inspector setup ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#validating-server-public-key) Validating Server Public Key Without validating the server public key, the initial handshake is vulnerable to MITM attacks. Although validating the server key might not be possible in all hosting modes (especially player hosted games may be difficult), it is still recommended to add to your game if possible. Out of the box, we provide 3 modes of validation: #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#off) Off Nothing is validated, this is the default. Good for development and where validation is simply not possible. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#list) List Public keys are validated from a list of trusted keys that are "baked in" to the build. This mode is good for games that host servers for their players and the easiest to use, simply pre-generate a key file to load on the server which will automatically add it to the list. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FFAVHBOjzgKQgLAZoBcRC%252Fimage.png%3Falt%3Dmedia%26token%3D8bd1f98b-99b8-4f16-bc33-f6e72d3ecf8e&width=768&dpr=3&quality=100&sign=d3394c8b&sv=2) Inspector showing Generate Key Pair Button ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fa0XMxAOSUHKpTj37uHSy%252Fimage.png%3Falt%3Dmedia%26token%3D2ede3cdb-a21c-44f1-8c88-3897fb724dab&width=768&dpr=3&quality=100&sign=83860ea5&sv=2) Dialogue to automatically add key to the trusted list #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#callback) Callback In this mode, when a client connects to a server, it will call the `EncryptionTransport.onClientValidateServerPubKey` callback which is expected to return `true`for a valid key. This allows for the most flexibility and allows you to validate public keys by exchanging them before connecting, for example from the lobby service, or a login api. Once a client or server is running, the fingerprint can be retrieved from `EncryptionTransport.EncryptionPublicKeyFingerprint` (and the serialized public key itself from`EncryptionTransport.EncryptionPublicKey`). ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#performance) Performance The transport currently uses BouncyCastle for all cryptography, which is very heavy on allocations. We are planning to address this in a future update through both, improving BouncyCastle itself and providing a native library for most platforms to do the bulk of the work, the AES en-/decryption. [PreviousFizzyFacepunch Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/fizzyfacepunch-transport) [NextEdgegap Transportschevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/edgegap-transports) Last updated 2 years ago * [Technical details](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#technical-details) * [Usage](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#usage) * [Validating Server Public Key](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#validating-server-public-key) * [Performance](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport#performance) --- # Transports | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports#built-in-transports) Built-in Transports ------------------------------------------------------------------------------------------------------------------- These transports are included with Mirror. * [KCP](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport) UDP transport based on kcp.c, line-by-line translation to C# * [Telepathy](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport) - Simple, message based, MMO Scale TCP networking in C#. And no magic. * [Simple Web Sockets](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport) - WebGL transport layer for Mirror that target browser clients. * [Multiplexer](https://mirror-networking.gitbook.io/docs/manual/transports/multiplex-transport) - Bridging transport to allow a server to handle clients on different transports concurrently, for example desktop clients using Telepathy together with WebGL clients using Websockets. * [Latency Simulation](https://mirror-networking.gitbook.io/docs/manual/transports/latency-simulaton-transport) - Middleman transport to test non-ideal network conditions * [Encryption](https://mirror-networking.gitbook.io/docs/manual/transports/encryption-transport) - Middleman transport to encrypt a different transport * [Edgegap Relay Transports](https://mirror-networking.gitbook.io/docs/manual/transports/edgegap-transports) - Transports to utilize [Edgegaps Destributed Relayarrow-up-right](https://edgegap.com/en/platform/distributed-relay) Service [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports#additional-transports) Additional Transports ----------------------------------------------------------------------------------------------------------------------- These transports are maintained by third parties outside of Mirror. * [Monkearrow-up-right](https://github.com/JesusLuvsYooh/monke) - plug and play encrypted middleman transport layer for mirror. * [Ignorance](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance) - reliable and unreliable sequenced UDP transport based on ENet. * [LiteNetLibTransport](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport) - UDP transport based on [LiteNetLibarrow-up-right](https://github.com/RevenantX/LiteNetLib) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports#relay-transports) Relay Transports ------------------------------------------------------------------------------------------------------------- These transports are maintained by third parties and use relay infrastructure to connect clients to servers behind firewalls / NAT. * [Steam - FizzySteamworks](https://mirror-networking.gitbook.io/docs/manual/transports/fizzysteamworks-transport) - Transport utilizing Steam P2P network, building on [Steamworks.NETarrow-up-right](https://github.com/rlabrecque/Steamworks.NET) . * [Epic - Epic Online Servicesarrow-up-right](https://github.com/Ludogram/EpicOnlineTransport) - Relay transport utilizing Epic's free relay service. * [LRM - Light Reflective Mirrorarrow-up-right](https://github.com/Speidy674/Light-Reflective-Mirror) - Relay transport for WebGL clients. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports#changing-transports) Changing Transports ------------------------------------------------------------------------------------------------------------------- Changing transports is very easy and only requires a few steps: * Go to the game object that has the Network Manager component * Add another transport script via the Add Component button * Drag the transport script to the "Transport" field in the Network Manager * Remove the old transport script (optional) If you have connection issues with a transport that requires port forwarding, make sure to port forward the correct protocol (TCP / UDP). [PreviousExecution Orderchevron-left](https://mirror-networking.gitbook.io/docs/manual/faq/execution-order) [NextKCP Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/kcp-transport) Last updated 1 year ago * [Built-in Transports](https://mirror-networking.gitbook.io/docs/manual/transports#built-in-transports) * [Additional Transports](https://mirror-networking.gitbook.io/docs/manual/transports#additional-transports) * [Relay Transports](https://mirror-networking.gitbook.io/docs/manual/transports#relay-transports) * [Changing Transports](https://mirror-networking.gitbook.io/docs/manual/transports#changing-transports) --- # Ignorance | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#what-is-ignorance) What is Ignorance? -------------------------------------------------------------------------------------------------------------------------- Ignorance is a reliable UDP transport layer that utilizes the native ENET C Networking library via a [custom fork of ENet-CSharparrow-up-right](https://github.com/SoftwareGuy/ENet-CSharp) providing an reliable and unreliable sequenced UDP transport for both 64Bit desktop operating systems (Windows, Mac OS and Linux) and Mobile OSes (Apple iOS and Android). It also supports up to 255 channels and 4096 clients connected at one time. ENET is a solid reliable UDP C++ network library that is mature and stable. Unity's LLAPI needs a replacement. Ignorance was designed with that goal in mind - fill the gap and provide a solid, performant RUDP transport for Mirror. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#why-ignorance-over-the-unity-llapi) Why Ignorance over the Unity LLAPI? ------------------------------------------------------------------------------------------------------------------------------------------------------------ Unity's old LLAPI was horridly inefficient, and lots of testing has shown that you will get reduced performance using Unity LLAPI in your project. This is due to the design of the old networking code - Unity Tech made "by design" decisions and poor bug fixes that were seen to other developers as band-aids over a gaping wound. They did not care about performance or bug fixes. Unity LLAPI was also closed source, meaning the Mirror developers could not take a knife to it and make it better. This is where the concept of Ignorance took shape. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#who-develops-ignorance) Who develops Ignorance? ------------------------------------------------------------------------------------------------------------------------------------ [Coburnarrow-up-right](http://github.com/softwareguy) is the lead developer of the transport. Oiran Studio actively uses this transport for networked game projects. It is currently also being utilized by some game projects, where you can find on the Mirror Discord server. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#why-would-i-want-to-use-reliable-udp-over-tcp) Why would I want to use reliable UDP over TCP? ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * if you have realtime communications that you need speed over reliability (VoIP...) * if you need channels * if you need custom channel send types * if you need a data hose for your game (a first person shooter, racing game, etc) [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#why-wouldnt-i-want-to-use-reliable-udp-over-tcp) Why wouldn't I want to use reliable UDP over TCP? --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * if you have **mission critical** things (as in, data **NEEDS** to go from A and B, no exceptions) * if you need fully reliable network protocol * if you're paranoid * if you're making a Minecraft-like game and need to keep everyone in sync [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#i-want-to-know-more-about-reliable-udp) I want to know more about reliable UDP... ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- A little explanation is required. UDP is best described as a "shattershot" data transmission protocol, which means you just spray and pray that packets at a destination and hope for the best. The remote destination may or may not receive those packets, nor are they going to be in order. For example, if you have a packet stream that is: ...then it may end up like any of the following on the other end due to packets arriving out of order. A dot in the following example means that packet went missing. For example, say you lost a packet and that contained a player's health update. Everyone else might know they took 69 damage, but that client will still have the old value of say, 72 health. Without reliable UDP, you can become out of sync very quickly. When you're out of sync, the game is over - everything will start operating very strangely. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#sequencing-and-reliable-delivery) Sequencing and Reliable Delivery ------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#sequencing) Sequencing **Sequencing** basically tags packets so they know what number they are when being dispatched. So if you send packets `100, 101, 102` to the remote destination, the other end will reconstruct the packet in that order rather than in a different order (like `101, 100, 102`). If a packet is missing, it'll be skipped but the network library will take note that it's missing and compensate. **Reliable** mode just tells ENET to send this while waiting for the remote to acknowledge packet reception, before claiming it was 'lost'. ENET will still classify said packets as lost if it doesn't hear back from the remote, but it will retransmit them to compensate for lossy connections or high latency situations. Reliable mode tries to emulate some of TCP's resending if not acknowledged in time, but as UDP does not have all the overhead TCP protocol has, it adds some packet overhead. Ignorance comes with two channels in both Reliable and Unreliable mode by default. There are other channel modes that developers can test as different ones might suit different loads, but the average person does not need to worry about this. Ignorance comes with sane defaults out of the box. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#does-ignorance-support-websockets) Does Ignorance support Websockets? ---------------------------------------------------------------------------------------------------------------------------------------------------------- No, it does not. Mirror comes with built-in websockets support. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#where-can-i-get-ignorance) Where can I get Ignorance? ------------------------------------------------------------------------------------------------------------------------------------------ [Grab the latest build from the releases page on the Ignorance repositoryarrow-up-right](https://github.com/SoftwareGuy/Ignorance) . Simply import the Unity Package from the release you downloaded. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#where-can-i-get-support) Where can I get support? -------------------------------------------------------------------------------------------------------------------------------------- You can get support by opening a issue ticket on the [Ignorance repository issue trackerarrow-up-right](https://github.com/SoftwareGuy/Ignorance/issues) or the #ignorance channel in the Mirror Discord server. [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#i-still-dont-understand-what-this-transport-is-my-head-is-spinning-help) I still don't understand what this transport is, my head is spinning, help! ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Come by the Discord and we'll do our best to explain it in plain English. [PreviousLatency Simulation Transportchevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/latency-simulaton-transport) [NextLiteNetLib Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport) * [What is Ignorance?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#what-is-ignorance) * [Why Ignorance over the Unity LLAPI?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#why-ignorance-over-the-unity-llapi) * [Who develops Ignorance?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#who-develops-ignorance) * [Why would I want to use reliable UDP over TCP?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#why-would-i-want-to-use-reliable-udp-over-tcp) * [Why wouldn't I want to use reliable UDP over TCP?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#why-wouldnt-i-want-to-use-reliable-udp-over-tcp) * [I want to know more about reliable UDP...](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#i-want-to-know-more-about-reliable-udp) * [Sequencing and Reliable Delivery](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#sequencing-and-reliable-delivery) * [Sequencing](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#sequencing) * [Does Ignorance support Websockets?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#does-ignorance-support-websockets) * [Where can I get Ignorance?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#where-can-i-get-ignorance) * [Where can I get support?](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#where-can-i-get-support) * [I still don't understand what this transport is, my head is spinning, help!](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance#i-still-dont-understand-what-this-transport-is-my-head-is-spinning-help) Copy 1 2 3 4 5 6 7 Copy 7 6 1 3 2 4 5 7 6 . . 4 . 1 . . . . 1 2 3 1 2 3 5 4 6 7 --- # FAQ | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#how-to-send-sync-custom-data-types) How to Send/Sync custom data types? ------------------------------------------------------------------------------------------------------------------------------------------- Mirror can automatically create Serialization functions for many custom data types when your scripts are compiled. For example, mirror will automatically create a functions for `MyCustomStruct` so that it can be sent without any extra work. Copy [ClientRpc] public void RpcDoSomething(MyCustomStruct data) { // do stuff here } struct MyCustomStruct { int someNumber; Vector3 somePosition; } For More details * [Data Typesarrow-up-right](https://mirror-networking.gitbook.io/docs/guides/data-types) * [Serializationarrow-up-right](https://mirror-networking.gitbook.io/docs/guides/serialization) [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#how-do-i-connect-to-another-mirror-instance) How do I connect to another Mirror instance? ------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#to-another-instance-on-the-same-device) To another instance on the same device Ensure you're connecting to "localhost". Localhost basically means "local host" which is your local machine. Make sure the Network Address field on NetworkManager is set to "localhost", or if using the NetworkManagerHUD that the text box is "localhost". Make sure you don't include the quotes. Please note that this won't work on mobile devices, as neither iOS or Android support running two instances of the same application side-by-side. This is more suited for desktop testing and development use. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#to-another-instance-on-the-same-network-lan) **To another instance on the same network (LAN)** Make sure the Network Address field on NetworkManager is set to the LAN IP of the host, or if using the NetworkManagerHUD that the text box is set to the LAN IP of the host. A correct setting, for example, is "192.168.8.100", "10.0.0.100", "172.16.42.69" An incorrect setting, for example, is "localhost" or "203.200.110.100" _In some cases you may need additional steps, check below_ To check your LAN IP on Windows you can open PowerShell/Command Prompt and use the `ipconfig` command, then under your current adapter (ethernet/wifi/etc) look for the _IPv4 Address_ entry like so: `IPv4 Address. . . . . . . . . . . : 192.168.x.x` On Mac OS, you can use Network Settings in the Settings application, while on Linux you can either use `ifconfig`, `ip addr` or a GUI like _NetworkManager_ or _wicd_ to get your LAN IP depending if you are running a desktop environment or going commando at the command line. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#to-another-instance-internet-wan) To another instance (Internet/WAN) Set the networkAddress field to be the IP address of the host (google 'whats my IP') circle-exclamation This section does not cover Relays, Dedicated VPSes or Headless Features. For this to work, you will need to do **some** of the following, most of these depend on your set up and router: * **Port forwarding**: * Ensure your ISP allows you to host servers on your own connection, some ISPs do not allow this and will filter incoming connections. **If in doubt, check with your ISP.** _Knowledge is power._ * Ensure your ISP allows you to change settings on your router. Some can be very strict and reset settings that you changed randomly. * Either forward your game port (default is 7777) for your PC's local IP, 192.168.1.20 for example. Ensure that you specify the correct protocol, incoming UDP connections won't work if you have it only set to accept incoming TCP connections and vice versa. If your router supports it, you can use the "BOTH" setting to bypass this headache; **OR** * Pull a quick (but less safe) trick add that local IP to the routers' DMZ for desperate measures. triangle-exclamation DMZ can be a very useful tool but **be warned:** _with great power comes great responsibility!_ The computer that has the IP address you specify will be exposed on the internet without the router firewall filtering bad inbound traffic. That means if you're running any private web server or application, you may have intrusions from others located elsewhere on the internet. **DO NOT USE** this DMZ option if you are running an unpatched operating system (for example, a old version of Microsoft Windows) or you risk your computer security being compromised. Ensure your security is enabled and your anti-virus/anti-malware software is fully updated before playing with DMZ settings. * **PC Firewalls**: * You can turn it off for a quick test to see if your firewall is being annoying. **Make sure you turn it back on later.** * Manually allow the editor and any builds you create in your Firewall settings. * Try from a build rather than the Unity Editor as sometimes Unity Editor can be janky. * Some anti-virus/mobile devices may have additional blocking layers: * If you can, try turning them off for a quick test. **Ensure you turn it back on later.** * In rare cases ISPs or companies/schools block ports and connections, this is harder to adjust yourself. If you need more help it is best to google for guide for your setup and router. An sure-fire alternative to the above is to use a Dedicated Server/VPS or use a Relay. [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#host-migration) Host Migration -------------------------------------------------------------------------------------------------- Host migration alternatives and work-around. Host migration as of writing is not built into Mirror, and it is best to avoid Host Migration completely if you can. Below are some tips as to why, and how you can add a host migration-like alternative. * Dedicated hosts should rarely ever be closed, if you are doing games that need to stay open such as MMO's. * Short arena maps, take players back to the games list/matchmaker, so they can just join another, nice and simple. The work around is to basically fake the host migration, store info of a backup host on players game, upon disconnection, reconnect everyone in the game to that new host, then restore positions and variable data back to how it was before the original host disappeared. * Test players connections when they join, find one with unblocked ports, and decent ping/latency. * Send this players data (IP and Port) on all connected players games. * Save various player info, either locally or on that backup host, such as player positions, health etc * Upon disconnection from server, call a function to connect to the backup hoster. For example, `StartClient( BackupIP - BackupPort )` * As the scenes will most likely reset, along with players re-spawning, you now need to set player position back to your stored one that was saved either via checkpoints, or in the disconnect detection callback. * Cover all this up with a UI, saying please wait (optional, should happen in the blink of an eye). Depending on what your game is like, it'll either be easy or difficult to add the work-around. An example of these are: * (easier) A game only needing player position data such as "Fall Guys". * (difficult) Forge of Empires, a game where created objects are placed, soldiers, vehicles, various other crafts and upgrades, all with their own levels/stats. [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#master-list-servers-and-simple-matchmaker) Master / List Servers and Simple Matchmaker ---------------------------------------------------------------------------------------------------------------------------------------------------------- A database of world-wide registered host data. All the hosts, dedicated or player hosts, get added into a list database, players get the list and can choose who to join. Using a list server means players do not have to manually enter IP addresses and Ports, it is all done behind the scenes, and works for localhost, LAN, and WAN connection types. You can show as much, or as little data as you like to the players, such as host name, type (deathmatch), player count (45 / 50), ping, enemy difficulty, map, region etc * Node ListServer: Free, but you host the files yourself on an unblocked PC, like a VPS. Has a wide variety of customisable features, best option if you want self hosted dedicated games. * Light Reflective Mirror: This is a list server and a relay, it is free, but you host and manage the files yourself. Relays offer an unblocked route of traffic, but at the cost of extra latency/increased ping. This relay will test for a direct connection first, then fallback to routed traffic if that fails. Both the list server and relayed traffic is optional, you can use one part, and not the other. This is the best option for player hosted games, where router port blocks are common. * Epic and Steam, these are hosted for you. Check Discords Addons and Transports sections for more information, and for other non-listed ways of matchmaking and list servers. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#simple-matchmaker) Simple Matchmaker * You can make matchmakers out of these list servers, simply hide the list to players, have them auto join a game with space. You could also filter out various requirements the player has set, for example, "USA" Region only, or "Lava Island" map. [hashtag](https://mirror-networking.gitbook.io/docs/manual/faq#how-to-get-the-player-count) How to get the player count? ----------------------------------------------------------------------------------------------------------------------------- There are a few ways to do this, each with their own unique benefit. **NetworkServer.connections.Count** * Socket connections, includes people without spawned prefabs, non authenticated, or that may have bugged out during spawn, but have connected temporarily (Android users minimising game). Only host / server can check this. **NetworkManager.singleton.numPlayers** * Number of active spawned player objects on the server (only the host / server can check this) **Find by GameObject Tag** * Works client-side, doesn't require network code, and a good way to distinguish between player states, by applying gameobject tags for certain situations, for example, 'not ready/Default', 'Dead', 'Spectator'. [PreviousNetGraphchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/netgraph) [NextExecution Orderchevron-right](https://mirror-networking.gitbook.io/docs/manual/faq/execution-order) Last updated 4 years ago * [How to Send/Sync custom data types?](https://mirror-networking.gitbook.io/docs/manual/faq#how-to-send-sync-custom-data-types) * [How do I connect to another Mirror instance?](https://mirror-networking.gitbook.io/docs/manual/faq#how-do-i-connect-to-another-mirror-instance) * [To another instance on the same device](https://mirror-networking.gitbook.io/docs/manual/faq#to-another-instance-on-the-same-device) * [To another instance on the same network (LAN)](https://mirror-networking.gitbook.io/docs/manual/faq#to-another-instance-on-the-same-network-lan) * [To another instance (Internet/WAN)](https://mirror-networking.gitbook.io/docs/manual/faq#to-another-instance-internet-wan) * [Host Migration](https://mirror-networking.gitbook.io/docs/manual/faq#host-migration) * [Master / List Servers and Simple Matchmaker](https://mirror-networking.gitbook.io/docs/manual/faq#master-list-servers-and-simple-matchmaker) * [Simple Matchmaker](https://mirror-networking.gitbook.io/docs/manual/faq#simple-matchmaker) * [How to get the player count?](https://mirror-networking.gitbook.io/docs/manual/faq#how-to-get-the-player-count) Copy public GameObject[] playersArray; public void FindPlayersByTag() { playersArray = GameObject.FindGameObjectsWithTag("Player"); Debug.Log("Players found: " + playersArray.Length); } --- # Lag Compensation | Mirror Lag Compensation (aka Rollback) is needed for fast pace / first person shooter games. For MMORPGs, card games, round based games, strategy games, etc. this is not interesting. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation#why-lag-compensation) Why Lag Compensation ----------------------------------------------------------------------------------------------------------------------------------- Let's look at the most common reason why games need lag compensation. Consider a first person shooter like Counter-strike. There are two players on the server: you, and your friend. The server synchronizes your friend's position to you. It takes let's say **50 milliseconds**. You fire at your friend by using a Mirror `[Command] CmdFire(Vector3 direction)`. The `[Command]` takes another **50 ms** to reach the server. The Server then checks if you hit your friend, and applies damage. triangle-exclamation In the **100 ms** that passed, your friend has already moved two steps to the left. As result, you'll always **miss the shot**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FBsAp6YD41HI4Jl7m5Kwp%252Fimage.png%3Falt%3Dmedia%26token%3D6fb72943-0c38-4bfb-8166-10bd51e715a3&width=768&dpr=3&quality=100&sign=c2b3e15e&sv=2) Where you see your friend, and where your friend actually is. Image from [Valve's Articlearrow-up-right](https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking) . This is why you need lag compensation for high paced / first person shooter games. Otherwise players will always need to aim ahead of their targets. circle-info On paper, this doesn't sound like a big deal. In practice, players will immediately complain that they don't hit where they aim. The difference between lag compensation turned on / off is very noticeable to everyone. For a more in-depth understand, please read through [Valve's Source Multiplayer Networking articlearrow-up-right](https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking) . It's a good read, and worth the time even if you don't understand all of it yet. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation#lag-compensation-with-mirror) Lag Compensation with Mirror --------------------------------------------------------------------------------------------------------------------------------------------------- Our Lag Compensation is split into two parts. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation#lagcompensation.cs-standalone-algorithm) LagCompensation.cs standalone Algorithm First, there's the standalone, Unity independent, C# LagCompensation.cs algorithm with full test coverage: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F0gAlpzBsLwvyIbEH7xu7%252F2023-07-05%2520-%252014-26-07%25402x.png%3Falt%3Dmedia%26token%3D1a3e807a-9de4-4e2c-bc97-47a392441739&width=768&dpr=3&quality=100&sign=ae01abfc&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F7K7UzfSFrWFfRioPEw8Z%252F2023-07-05%2520-%252014-28-43%25402x.png%3Falt%3Dmedia%26token%3D2b981c63-655a-453e-a4df-fc4fa65105a4&width=768&dpr=3&quality=100&sign=4a9dc830&sv=2) The algorithm can record and sample any History of type . In other words, you can custom fit it to your needs if you want to. Keep in mind that this is very low level, and it's easier to use the high level component instead! #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation#lag-compensator-component) Lag Compensator Component The second part: our `Lag Compensator` component: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F860jM7KgGF8zDYJUqHUM%252Fimage.png%3Falt%3Dmedia%26token%3D19075b0e-a714-4833-a008-d1690b206ada&width=768&dpr=3&quality=100&sign=b3c27f7c&sv=2) This hides all the magic in one component which automatically records a history of Collider snapshots in 3D. Simply add this to your Player object, and it'll handle everything for you! Next, find the place where your player is firing a weapon locally. There should be a \[Command\] like CmdFireWeapon() that sends the input to the server. This is where instead of checking if a player hit another player, we first ask Lag Compensation for the other player's position at the time when the player shot it. You can check our Shooter example to see this in action, it's as simple as: Note the above code is slightly simplified, but that's really all there's to it other than a few more optional configuration parameters in the LagCompensator's 'Check' functions. circle-info Our Lag Compensator is super easy to use, and you can still add more complex checks to if if needed. What matter is that our standalone LagCompensation.cs algorithm is generic , working with anything you need (2D, 3D, custom physics, etc.). circle-check Our Mirror Shooter demo uses the Lag Compensator. As of February 2024, it is almost complete and soon to be released! #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation#note-algorithm-minimal-example) Note: Algorithm Minimal Example If you prefer to not use the convenience LagCompensator component, then you can check our 'Lag Compensation' demo in the Examples folder. It's super simple, not even networked, and shows only the algorithm without the component. In other words: ignore this example if you are using the component! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FeAfGjulYtiriRCpvGugp%252F2023-06-29%2520-%2520lag%2520compensation%2520estimated%2520time%2520accurate%2520by%25206ms.png%3Falt%3Dmedia%26token%3D45604bc1-9ddc-4acb-b0a5-0b40c4d4ce65&width=768&dpr=3&quality=100&sign=db886b9d&sv=2) Mirror's Lag Compensation Example **This demo is very easy to understand:** * The filled **white square** is an object on the server * The outlined white squares are the **captures** taken every interval. * The **black square** is the object on the client, **lagging** behind by a few milliseconds * You click the black square, which calls a `CmdFire()` on the server. * If it highlights blue, you hit. If it highlights magenta, you didn't hit. * The **black square** is exactly one square behind the **white square**, which means you'll only hit if it lag compensation functions properly. This was Lag Compensation part one: the algorithm. You can use this in games _today_, you just need to adapt the demo to your needs. You also need to worry about rolling back the physics world, we don't have a demo for this _yet_. [PreviousConnection Qualitychevron-left](https://mirror-networking.gitbook.io/docs/manual/general/connection-quality) [NextClient Side Predictionchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction) Last updated 2 years ago * [Why Lag Compensation](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation#why-lag-compensation) * [Lag Compensation with Mirror](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation#lag-compensation-with-mirror) Copy [Client] void FireWeapon() { // show muzzle flash, play sound etc. locally // ... // check if anything was hit if (Physics.Raycast(camera.position, camera.position + camera.forward, out RaycastHit hit)) { Player target = hit.collider.GetComponent(); // notify the server CmdFiredWeapon(target, camera.position, hit.position); } } [Command] void CmdFiredWeapon(Player target, Vector3 originPoint, Vector3 hitPoint) { // check ammo etc. // ... // 'this' fired at 'target'. // we need to grab 'target's LagCompensator to find out where it was. LagCompensator compensator = target.GetComponent(); // next, we can use either of the compensator's 'Check...' functions. // viewer is the one who fired, so it's 'this' object. // Lag Compensator checks 'this' object's latency and then rewinds 'target's history by that time. if (compensator.RaycastCheck(this.connectionToClient, originPoint, hitPoint)) { // valid hit! } } --- # iOS AppStore | Mirror **iOS AppStore UDP** Mirror's default kcp Transport uses UDP sockets. When submitting your App to the App Store review process for the first time, some people's apps get rejected because Apple's VPN can't seem to handle UDP. It's not obvious to us why that is, but here are a few workarounds that people suggested: * cooper: "Submit your App with a TCP transport like Telepathy. Once approved, switch to KCP again in the next update. Supposedly this works." * Ninja: "The app reviews kept getting rejected until I essentially asked for manual intervention, and then it passed" * Use multiplexer for apple release, for example kcp as main and telepathy as backup transport. **iOS AppStore LAN Broadcasting** Follow the Xcode instructions to get the multicast networking permission from Apple. Add it to the app provisioning, then add the capability to the app itself, making sure you've properly added the entitlement to your app in Xcode. Latest versions may need this: Add NSLocalNetworkUsageDescription to the info.plist. Note: If LAN Broadcasting does not work, try another address, for example, change 0.0.0.0 to 255.255.255.255 (remember to rebuild after changing) This should get Network Discovery features working, Kudos to overmatch-iman, Sylvain and other Discord users for reporting back the working steps. [PreviousReady Up And Die!chevron-left](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die) [NextMirror Docker Guidechevron-right](https://mirror-networking.gitbook.io/docs/community-guides/mirror-docker-guide) Last updated 1 year ago --- # Resources | Mirror This page has a collection of links for learning and using Mirror. Some things this page includes * Video tutorials * Other guides * Example scripts Anything to add to this list? Please make a PR or ask in the discord. [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/resources#object-pooling) Object Pooling ------------------------------------------------------------------------------------------------------------------ * [Simple object pooling scriptarrow-up-right](https://gist.github.com/James-Frowen/46ca5e8fd76d62527be7b958ca8dbaf1) * [Advanced object pooling scriptsarrow-up-right](https://gist.github.com/James-Frowen/c2ab4cdc96165298518bd2db0781bbe6) [PreviousVideo Tutorialschevron-left](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials) [NextMirror Quick Start Projectchevron-right](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide) Last updated 5 years ago --- # Odin Inspector Support | Mirror If you are trying use Mirror together with Odin Inspector: Change `NetworkBehaviourInspector :` `**Editor**` to: `NetworkBehaviourInspector :` `**OdinEditor**` Then it should work! [PreviousUnity Canvas HUDchevron-left](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide) [NextReady Up And Die!chevron-right](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die) Last updated 2 years ago --- # Mirror Branding | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FW18HU9ILPhTABbeCxBWz%252Fmirror_icon_1950x1300_M_reviews.png%3Falt%3Dmedia%26token%3D121e9c0a-d2f2-4c7f-bf70-e3f81768d606&width=768&dpr=3&quality=100&sign=9e780211&sv=2) 1950 x 1300 ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FHybi3wXznrWQsopu2xQP%252Fmirror_icon_1200x630_M.png%3Falt%3Dmedia%26token%3Dcf1514ea-da97-4f32-abbb-619b5e2dd9ec&width=768&dpr=3&quality=100&sign=236f0016&sv=2) 1200 x 630 ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F72CLbcmkhoJRkjGbKO6S%252Fmirror_icon_512x512_M.png%3Falt%3Dmedia%26token%3D38df76f8-a179-438b-9c64-4d6c1ed92741&width=768&dpr=3&quality=100&sign=d520c244&sv=2) 512 x 512 ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F5XFdbhF2oDTUYHuy0pqk%252Fmirror_icon_160x160_M.png%3Falt%3Dmedia%26token%3De7bef4f4-d837-4a02-8616-b89acca0ce1f&width=768&dpr=3&quality=100&sign=c086bc2f&sv=2) 160 x 160 [PreviousGitbook Guidechevron-left](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide) [NextContributors Agreementchevron-right](https://mirror-networking.gitbook.io/docs/community-guides/contributors-agreement) Last updated 2 years ago --- # Mirror Docker Guide | Mirror To use Unity with Docker, you can try this Guide: [![Logo](https://docs.edgegap.com/~gitbook/image?url=https%3A%2F%2F1109547351-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Forganizations%252F95tKGN3dU93xhs9xa3Oe%252Fsites%252Fsite_mBjoG%252Ficon%252FsGgR2kUmXvukZ6WKoPWx%252Ffavicon.png%3Falt%3Dmedia%26token%3Dc18c8d4c-d17d-43f5-84d7-3b909e3e538d&width=48&height=48&sign=62ce0eb6&sv=2)Unity | Edgegap Docsdocs.edgegap.comchevron-right](https://docs.edgegap.com/docs/tools-and-integrations/unity-server-in-docker) Additionally, our friend Andrew Allbright shared a sample with Mirror running on Docker + Docker Compose: > The Mirror server is built as a dedicated linux server build and runs on an ubuntu server. The webGL assets are served from an nginx server. Another nginx container serves as a reverse proxy, so that the websocket connection is accepted. [![Logo](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2Fgithub.com%2Ffluidicon.png&width=20&dpr=3&quality=100&sign=49f2fdc4&sv=2)GitHub - aallbrig/unity-mirror-networking-containerizedGitHubchevron-right](https://github.com/aallbrig/unity-mirror-networking-containerized) [PreviousiOS AppStorechevron-left](https://mirror-networking.gitbook.io/docs/community-guides/ios-appstore-udp) [NextGitbook Guidechevron-right](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide) Last updated 3 years ago --- # Unity for MMORPGs | Mirror A lot of users want to make MMORPGs with Unity / Mirror. While Unity is not the best choice for game servers, it does bring great advantages. This post was our reply to a user on the Unity forums asking about [MMOs & Unityarrow-up-right](https://forum.unity.com/threads/mmo-server-with-unity.1410480/#post-8868246) . Make sure to also check out our very old "[How to make an MMORPGarrow-up-right](https://noobtuts.com/articles/how-to-make-a-mmorpg) " guide, which is essentially what started Mirror in the first place. \[...\] The reason why you would use Unity for the client and the server is productivity. Sharing physics, assets, navigation and code saves you a lot of time. Several smaller MMOs have been made this way, and you can target about 200-300 CCU per Unity server instance. For example, Inferna, Samutale and Naica are MMOs which were made entirely in Unity (Mirror). [![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2Fforum.unity.com%2Fproxy.php%3Fimage%3Dhttps%253A%252F%252Fuser-images.githubusercontent.com%252F16416509%252F178149040-b54e0fa1-3c41-4925-8428-efd0526f8d44.jpg%26hash%3D06e9b9a127560446c7522abeb8b17e09&width=300&dpr=3&quality=100&sign=8a6cb998&sv=2)arrow-up-right](https://forum.unity.com/proxy.php?image=https%3A%2F%2Fuser-images.githubusercontent.com%2F16416509%2F178149040-b54e0fa1-3c41-4925-8428-efd0526f8d44.jpg&hash=06e9b9a127560446c7522abeb8b17e09) Note that the lower your tick rate, the more CCU you can achieve. For example, if your server runs at 60 Hz, that gives you 16 ms to update the whole world. If your server runs at 10 Hz, that gives you 100 ms. With 6x more time to update, you can probably have 2-3x more CCU. This is how many early MMOs achieved 500+ CCU already 15 years ago. Many of them ran at 10 Hz or less. The downside is extra latency. But hey, 500 CCU 😄. Keep in mind that Unity is not a great choice for game servers if you care about robustness, stability, scale. C# standalone projects (outside of Unity) can run on netcore, which is significantly faster and more stable. Outside of Unity you also have more choices for programming languages which may be better suited for high scale / high performance servers. * Go is worth learning. A concurrent language developed by google for scalable systems. Much easier to do multithreading than with C#, due to go-routines. Also garbage collected, like C#. * Rust is great too. Bare metal C/C++ performance, but with memory safety. Multithreading is great too, because Rust protects you from data races (unlike Go and C#). Not garbage collected, so there won't be GC pauses to worry about. * C# is still great choice. However, some of the low level networking defaults aren't great. For example, there's an ongoing discussion about C# UDP socket allocations [herearrow-up-right](https://github.com/dotnet/runtime/issues/30797) . Allocations require garbage collection, which introduces GC pauses, which introduces performance issues in high scale servers. Worth noting that Unity is in the process of switching to netcore. That would be great for game servers! **TL;DR:** Unity is the slowest, most unstable solution for game servers. But it's also the most productive. Pick one 👍 [PreviousMirror Quick Start Projectchevron-left](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide) [NextUnity Canvas HUDchevron-right](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide) Last updated 3 years ago --- # SSL | Mirror circle-info NOTE: WebGL performs a lot better with a Reverse Proxy, and that's generally easier to set up and maintain than using cert.json and PFX files. Go to the [Reverse Proxy](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/reverse-proxy) page for instructions. If you host your webgl build on a HTTPS domain you will need to use the secure web socket protocol (`wss://`). WSS requires a SSL certificate set up on your Mirror game server for basic scenarios or on your gateway server for "reverse proxy" scenarios. You will also have to ensure the "Client Use WSS" option is set on the transport. For the following sections we will demonstrate how to obtain SSL certificates using [Let's Encryptarrow-up-right](https://letsencrypt.org/) for the domain `simpleweb.example.com`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#pre-setup) Pre-Setup * You need a domain name and the ability to edit DNS records * A DNS record should point to your webgl game client (normally hosted on port 443) * A DNS record should point to your Mirror game server * Set up virtual machine in the cloud: [How to set up a Google cloud serverarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/DevServer/gcloud/index.html) circle-info NOTE: you may need to open port 80 for `certbot` operations. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#get-cert) Get Cert Follows guides here: [https://letsencrypt.org/getting-started/arrow-up-right](https://letsencrypt.org/getting-started/) [https://certbot.eff.org/instructionsarrow-up-right](https://certbot.eff.org/instructions) Find the instructions for your server version. Below is link for `Ubuntu 18.04 LTS (bionic)` [https://certbot.eff.org/instructions?ws=nginx&os=ubuntubionicarrow-up-right](https://certbot.eff.org/instructions?ws=nginx&os=ubuntubionic) For instruction 7 After filling in details you will get a result like this `simpleweb.example.com` should be your domain ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#create-cert.pfx) Create cert.pfx To create a pfx file that SimpleWebTransport can use run this command in the `/etc/letsencrypt/live/simpleweb.example.com/` folder You will be asked for a password; you can set a password or leave it blank. You might need to be superuser in order to do this. Note: Currently the mono version shipped with unity is unable to load pfx files generated by OpenSSL version 3. You will have to add the `-legacy` command line argument to the openssl command above to generate a compatible pfx file. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#using-cert.pfx) Using cert.pfx You can either copy the cert.pfx file to your server folder or create a symbolic link. Using Move Using Symbolic link #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#create-cert.json-file) Create cert.json file Create a `cert.json` that SimpleWebTransport can read Run this command in the `~/path/to/server/` folder If you left the password blank at cert creation: If you set up a password "yourPassword" at cert creation: #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#run-your-server) Run your server After the `cert.json` and `cert.pfx` are in the game server folder like this Then make the server file executable To run in the active terminal use To run in background use To keep the game server running even after you close your ssh session use > `nohup` means: the executable will keep running after you close your ssh session the `&` sign means: that your server will run in background > you may need to use `sudo` to run if you created a symbolic link #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#connect-to-your-game) Connect to your game Test everything is working by connecting a game client to the game server using either the unity editor as a game client or using your deployed webgl build as the game client. Set your domain (eg `simpleweb.example.com`) in the hostname field and then start a client. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#debugging-ssl) Debugging SSL To check if your pfx file is working outside of unity you can use `pfxTestServer.js` ([srcarrow-up-right](https://github.com/James-Frowen/SimpleWebTransport/blob/master/DebugScripts~/node~/pfxTestServer.js) ). [PreviousHA Proxychevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/reverse-proxy/linux/ha-proxy) [NextMultiplex Transportchevron-right](https://mirror-networking.gitbook.io/docs/manual/transports/multiplex-transport) Last updated 2 years ago * [Pre-Setup](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#pre-setup) * [Get Cert](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#get-cert) * [Create cert.pfx](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#create-cert.pfx) * [Using cert.pfx](https://mirror-networking.gitbook.io/docs/manual/transports/websockets-transport/ssl#using-cert.pfx) Copy sudo certbot certonly --standalone Copy IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/simpleweb.example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/simpleweb.example.com/privkey.pem Your cert will expire on 2021-01-07. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le Copy openssl pkcs12 -export -out cert.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem Copy su cd /etc/letsencrypt/live/simpleweb.example.com/ Copy mv /etc/letsencrypt/live/simpleweb.example.com/cert.pfx ~/path/to/server/cert.pfx Copy ln -s /etc/letsencrypt/live/simpleweb.example.com/cert.pfx ~/path/to/server/cert.pfx Copy echo '{ "path":"./cert.pfx", "password": "" }' > cert.json Copy echo '{ "path":"./cert.pfx", "password": "yourPassword" }' > cert.json Copy GameServerFolder |- demo_server.x86_64 |- cert.json |- cert.pfx Copy chmod +x demo_server.x86_64 Copy ./demo_server.x86_64 Copy ./demo_server.x86_64 & Copy nohup ./demo_server.x86_64 & --- # Video Tutorials | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUfzdN8bc6bj_j0zmXN%252F-MUg-9kYFeD0F9jv6SLn%252F2021-03-01_12-16-30%25402x.png%3Falt%3Dmedia%26token%3D956c33d6-7cc1-42ce-bf3e-220d7f3dcdb8&width=768&dpr=3&quality=100&sign=ec08628a&sv=2) Community Video Tutorials ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials#english) English * [**Online Shooter with Mirror**arrow-up-right](https://www.youtube.com/watch?v=j2so32ZlMoU&t=2s) - Jason Weimann * [**Mirror Multiplayer by Dapper Dino**arrow-up-right](https://www.youtube.com/playlist?list=PLS6sInD7ThM1aUDj8lZrF4b4lpvejB2uB) **-** Tutorials that explain how to implement different features using Mirror. * [**Mirror Video Series**arrow-up-right](https://www.youtube.com/playlist?list=PLxadUPU23Hsmcy-YeZWCykywonNti3Yoj) - Home Slice Game Dev * [**Unity + Mirror Networking Tutorials by Shrine Wars**arrow-up-right](https://www.youtube.com/playlist?list=PLXEG2omgKgCapAmGe20XBgd87rmxFdKhK) **-** Explains the basics about Networking with Unity and Mirror. * [**Mirror Networking Tutorials by Jared Brandjes**arrow-up-right](https://www.youtube.com/playlist?list=PLDI3FQoanpm1X-HQI-SVkPqJEgcRwtu7M) **-** Long tutorials explaining how to set up lobbies and matchmaking with Mirror. * [**Unity/Mirror 2D Tabletop Card Game**arrow-up-right](https://www.youtube.com/watch?v=Agw2kPINMdU&list=PLCbP9KGntfcFTL19eDZsWSkVMfXANF7-U&index=1) - by M.S. Farzan ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials#german) German * [**Multiplayer Anwendung in Unity erstellen - Mirror Networking**arrow-up-right](https://www.youtube.com/watch?v=p-PW6FZtgV4&feature=youtu.be) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials#french) French * [**Recreating 'Among Us' by Lignus**arrow-up-right](https://www.youtube.com/watch?v=j5ja-pKz05A) **-** A tutorial using Unity and Mirror to recreate the famous game. (Tip: Do not speak these Languages? Set Youtube captions to on, and Auto Translate -> Your Language) [PreviousCommunity Translationschevron-left](https://mirror-networking.gitbook.io/docs/community-guides/community-translations) [NextResourceschevron-right](https://mirror-networking.gitbook.io/docs/community-guides/resources) Last updated 2 years ago * [English](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials#english) * [German](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials#german) * [French](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials#french) --- # Scene + Distance | Mirror Combines [Scene](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene) and [Distance](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance) Interest Management. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FXh3D7qSvcDpUGf0tXPFJ%252Fimage.png%3Falt%3Dmedia%26token%3D11942256-4157-4aaf-84e7-721cc9844bb8&width=768&dpr=3&quality=100&sign=ba313ac8&sv=2) Scene Distance Interest Management You will need to add Distance Custom Range components to any large, networked objects in the scene, especially an Environment object, terrains, or ground planes that have a pivot in the center of the scene which would be unusually far from the player when they're near the scene edges. [PreviousScenechevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene) [NextMatchchevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/match) Last updated 1 year ago --- # Contributors Agreement | Mirror Mirror is MIT licensed. [![Logo](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2Fgithub.com%2Ffluidicon.png&width=20&dpr=3&quality=100&sign=49f2fdc4&sv=2)Mirror/LICENSE at master · MirrorNetworking/MirrorGitHubchevron-right](https://github.com/vis2k/Mirror/blob/master/LICENSE) When contributing, you agree that we include your contribution under the same license. Thanks, _Mirror Team_ [PreviousMirror Brandingchevron-left](https://mirror-networking.gitbook.io/docs/community-guides/mirror-branding) [NextDocumentation Licensechevron-right](https://mirror-networking.gitbook.io/docs/community-guides/documentation-license) Last updated 4 years ago --- # Documentation License | Mirror Mirror is MIT licensed The documentation is also MIT licensed. MIT License Copyright (c) 2015, Unity Technologies Copyright (c) 2019, vis2k, Paul and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [PreviousContributors Agreementchevron-left](https://mirror-networking.gitbook.io/docs/community-guides/contributors-agreement) Last updated 1 year ago --- # Community Translations | Mirror Some community members have translated the Mirror documentation to their native languages. They may or may not be up to date. * **Russian** : [https://tuttik-fruttik.gitbook.io/mirror-networking-rus/arrow-up-right](https://tuttik-fruttik.gitbook.io/mirror-networking-rus/) [PreviousCheats & Anticheatschevron-left](https://mirror-networking.gitbook.io/docs/security/cheating) [NextVideo Tutorialschevron-right](https://mirror-networking.gitbook.io/docs/community-guides/video-tutorials) Last updated 2 years ago --- # Cheat Protection Stages | Mirror **Source:** [https://forum.unity.com/threads/help-me-choose-networking-solution-for-formation-tactics-game.1340309/arrow-up-right](https://forum.unity.com/threads/help-me-choose-networking-solution-for-formation-tactics-game.1340309/) \[Cheat Protection\] is a broad topic, with different stages of protections that you should be aware of. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#server-authority) **Server Authority** It would be wise to implement almost all game logic with **server authority** first, before worrying about client sided anti cheat. For example, if a player's **health** is client authoritative then no amount of client sided anti cheat will protect you from hackers attaining god mode. Where as with server authority, you would not ever ask the client about the current health. Instead, the server would tell the client about its health and make all decisions related to health, and validate all of the client's requests related to health. For example, when requesting to use a potion, always ensure the player actually owns that potion, is not dead, etc. This essential makes health unhackable, unless you are able to access the server machine. However, certain aspects like **movement** can be quite hard to make both responsive and secure. It's certainly possible to implement all of your game state with server authority. Even for movement, where you might move the client immediately, send the movement to the server, validate if the move was legal, and then accept / reject it. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#minimizing-client-information) **Minimizing client information** That being said, clients may still gain advantages by simply reading state from memory without manipulating it. For example, if your tactics game accidentally keeps all of the enemy's positions in memory, then hackers may attempt to extract it for their advantage. In this case, it would help to only send **relevant information** to the client. For example, many netlibs provide customizable interest management. You could implement Raycasting with some tolerance in order to check if a player sees another player's units. Otherwise, don't even send it to the player at all (in which case it can't be extracted from memory). ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#client-sided-anti-cheat) **Client sided anti-cheat** Lastly, even if your game is server authoritative and minimizes information sent to the client, there may still be cheats. For example, auto clicks, farm bots, aim bots and such. This is when you should start worrying about client sided anti cheat. But keep in mind that this is a catch & mouse game that you will not win, only delay. Reverse engineers have sophisticated tools to circumvent client sided anti cheats, and you will most likely not be able to compete with them all on your own. It gets so bad that some popular games need to move their anti cheat software out of userspace into the kernel, where it's harder for hackers to circumvent it. If your game is popular enough, it will be circumvented eventually. This is a very broad topic and there are lots of things you can do that I haven't mentioned, like obfuscation, virtualization, etc. But as mentioned, it would be wise to start with server authority & minimizing information sent to the client ![:)](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2Fforum.unity.com%2Fstyles%2Fdefault%2Fxenforo%2Fclear.png&width=300&dpr=3&quality=100&sign=161e9d5e&sv=2) On a side note, imho attempting to protect client sided hacks isn't ideal. Instead you should try to silently detect hacks, and then ban hackers after random amounts of time. This way a hacker would not know which particular action was detected. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#anti-cheat-with-mirror) **Anti Cheat with Mirror** Note that Mirror is server authoritative by default. Interest Management & SyncMode may be used to minimize information sent to clients. [PreviousSecurity Overviewchevron-left](https://mirror-networking.gitbook.io/docs/security/security-overview) [NextCheats & Anticheatschevron-right](https://mirror-networking.gitbook.io/docs/security/cheating) Last updated 3 years ago * [Server Authority](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#server-authority) * [Minimizing client information](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#minimizing-client-information) * [Client sided anti-cheat](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#client-sided-anti-cheat) * [Anti Cheat with Mirror](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages#anti-cheat-with-mirror) --- # Spatial Hashing | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing#spatial-hashing-interest-management) **Spatial Hashing Interest Management** -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- circle-exclamation For better performance try [Hex Spatial Hashing](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing) instead. First things first: **"Spatial Hashing"** sounds complicated so that we network programmers can stroke our egos. The technique is actually pretty simple, and if you used uMMORPG before then you probably remember this as **"Grid Checker"**. We go with "Spatial Hashing" anyway since that's the industry term. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing#setting-up) Setting Up Add the **Spatial Hashing Interest Management** component to the same object as your **Network Manager**: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FUQnA2MICbOCGUZheWPGE%252Fimage.png%3Falt%3Dmedia%26token%3D1a66b5f7-5490-4824-88f5-6463317d1ed9&width=768&dpr=3&quality=100&sign=a7e7e9cf&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing#how-it-works) **How It Works** Previously we **Vector3.Distance** checked each spawned entity against each connection. Instead, we put each spawned entity into a **Grid** and for each connection, we send all **8-neighbor** grid entries to it. This is extremely fast. In early uMMORPG tests, it was 30x faster than distance checking. The algorithm is less complex, so it scales well to large amounts of entities. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MWIEnySUkrRxUVX0X8d%252F-MWIFAsg-sK23fw3O_Cw%252Fimage.png%3Falt%3Dmedia%26token%3D277d227a-60b9-4092-8970-abbe6cc89d96&width=768&dpr=3&quality=100&sign=dda4e97&sv=2) Source: https://www.dynetisgames.com/2017/04/05/interest-management-mog/ circle-info Check out Mirror's **Benchmark** example. It uses Spatial Hashing and displays a runtime slider to let you play around with the visibility range. [PreviousInterest Managementchevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management) [NextHex Spatial Hashingchevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing) Last updated 3 months ago * [Spatial Hashing Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing#spatial-hashing-interest-management) * [Setting Up](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing#setting-up) * [How It Works](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing#how-it-works) --- # Match | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/match#match-interest-management) Match Interest Management ---------------------------------------------------------------------------------------------------------------------------------------------- triangle-exclamation Do not use this for physics-based games...use [**Scene Interest Management**](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene) instead. Match Interest Management is intended for non-physics games like card, board, arcade games. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/match#setting-up) Setting Up Add the **Match Interest Management** component to the same object as your **Network Manager**: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FQjXv0MO6gFKZHXHcN4I7%252Fimage.png%3Falt%3Dmedia%26token%3D8db59f4e-e66f-41ff-9c4b-e7ddf6c34554&width=768&dpr=3&quality=100&sign=b21c0028&sv=2) And add a **Network Match** component to all networked objects, including the player prefab, that will be involved in match play. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fo7hLM6gTAzpygCr7x1jq%252Fimage.png%3Falt%3Dmedia%26token%3D66d282d3-312c-4082-93fa-55fbafb7446c&width=768&dpr=3&quality=100&sign=56aa5b6a&sv=2) At runtime, assign the same `matchId` to players and objects that belong to the same match. See the **Multiple Matches** example included with Mirror for reference and inspiration. [PreviousScene + Distancechevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene-+-distance) [NextTeamchevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/team) Last updated 4 years ago * [Match Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/match#match-interest-management) * [Setting Up](https://mirror-networking.gitbook.io/docs/manual/interest-management/match#setting-up) --- # Security Overview | Mirror Cheats, Hacks, Exploits, Bots - multiplayer game security is a complex topic, mostly a catch & mouse game between devs and hackers. This section provides some basic overview on what to expect and how to mitigate issues before & after they arrive. circle-info We add content as questions come up. Feel free to ask us in Discord if you have concerns about your game's security measures. [PreviousEdgegap’s Dedicated Game Server Hosting – Plugin Guidechevron-left](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide) [NextCheat Protection Stageschevron-right](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages) Last updated 3 years ago --- # Components | Mirror These core components are included in Mirror: * [Network Animator](https://mirror-networking.gitbook.io/docs/manual/components/network-animator) The Network Animator component allows you to synchronize animation states for networked objects. It synchronizes state and parameters from an Animator Controller. * [Network Authenticator](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators) Network Authenticators facilitate integration of user accounts and credentials into your application. * [Network Discovery](https://mirror-networking.gitbook.io/docs/manual/components/network-discovery) Network Discovery uses a UDP broadcast on the LAN enabling clients to find the running server and connect to it. * [Network Identity](https://mirror-networking.gitbook.io/docs/manual/components/network-identity) The Network Identity component is at the heart of the Mirror networking high-level API. It controls a game object’s unique identity on the network, and it uses that identity to make the networking system aware of the game object. It offers two different options for configuration and they are mutually exclusive, which means either one of the options or none can be checked. * [Network Manager](https://mirror-networking.gitbook.io/docs/manual/components/network-manager) The Network Manager is a component for managing the networking aspects of a multiplayer game. * [Network Manager HUD](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud) The Network Manager HUD is a quick-start tool to help you start building your multiplayer game straight away, without first having to build a user interface for game creation/connection/joining. It allows you to jump straight into your gameplay programming, and means you can build your own version of these controls later in your development schedule. * [Network Ping Display](https://mirror-networking.gitbook.io/docs/manual/components/network-ping-display) Network Ping Display shows the Ping time for clients using OnGUI * [Network Rigidbody](https://mirror-networking.gitbook.io/docs/manual/components/network-rigidbody) The Network Rigidbody synchronizes velocity and other properties of a rigidbody across the network. * [Network Lerp Rigidbody](https://mirror-networking.gitbook.io/docs/manual/components/network-lerp-rigidbody) The Network Lerp Rigidbody component synchronizes position and velocity of a rigidbody across the network. * [Network Room Manager](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager) The Network Room Manager is an extension component of Network Manager that provides a basic functional room. * [Network Room Player](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player) The Network Room Player is a component that's required on Player prefabs used in the Room Scene with the Network Room Manager above. * [Network Start Position](https://mirror-networking.gitbook.io/docs/manual/components/network-start-position) Network Start Position is used by the Network Manager when creating player objects. The position and rotation of the Network Start Position are used to place the newly created player object. * [Network Statistics](https://mirror-networking.gitbook.io/docs/manual/components/network-statistics) Shows Network messages and bytes sent & received per second via OnGUI. * [Network Transform](https://mirror-networking.gitbook.io/docs/manual/components/network-transform) The Network Transform component synchronizes the movement and rotation of game objects across the network. Note that the network Transform component only synchronizes spawned networked game objects. [PreviousEdgegap Relaychevron-left](https://mirror-networking.gitbook.io/docs/manual/transports/edgegap-transports/edgegap-relay) [NextNetwork Animatorchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-animator) Last updated 2 years ago --- # Hex Spatial Hashing | Mirror Hex Spatial Hashing comes in both 2D and 3D versions, the latter handling hex-shaped volumetric space. Performance is improved over the original Spatial Hashing in part by only having 7 cells to consider instead of 9 (or 21 instead of 27 in 3D), and separate interval updates for static objects since they don't move, and reduced update workload by considering a minimum move distance to trigger rebuilds. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#setting-up) Setting Up Add the 2D or 3D Hex Spatial Hash component to the same object as Network Manager: ![Hex Spatial Hash 3D Component shown in the Inspector](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fs9xbL3QQgugeQTqt4hzJ%252Fimage.png%3Falt%3Dmedia%26token%3D18f55be9-f99b-45ac-a13d-9fa09ba80fa4&width=768&dpr=3&quality=100&sign=77ecde2&sv=2) Hex Spatial Hash 3D Component shown in the Inspector In the 2D version, there's a Check Method selector for which axes to use: ![Hex Spatial Hash 2D Component shown in the Inspector](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FFO15qeEVEQCbQEZ2q9qa%252FHex2D.png%3Falt%3Dmedia%26token%3Dcde9bc9f-ea73-4a7f-bb54-4a2701eca58b&width=768&dpr=3&quality=100&sign=476c70ff&sv=2) Hex Spatial Hash 2D Component shown in the Inspector Generally, you want to set the Vis Range to around 10% larger than your camera's Far Clip Plane. This lets Mirror spawn things in just before the camera will be able to see it, and let's Unity show your billboarding / higher LOD versions first to minimize the "pop-in" visual artifacts. Note that the Static Rebuild Interval for static objects is much slower than the normal Rebuild Interval. This is one of the performance improvements, since static objects don't move. We focus more of the workload on the moving player while iterating the static objects for new observers much less frequently. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#id-3d-hex-volumes) 3D Hex Volumes By setting the Vis Range and the Cell Height, you determine the size of the hex cell volumes around the player, as well as the levels above and below: ![Screenshot of Player in 3D Hex Volume](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F6HzQTq4EH3vJvCQHHS6C%252Fimage.png%3Falt%3Dmedia%26token%3D28cae873-541f-4a65-bb59-b40e6a544cf4&width=768&dpr=3&quality=100&sign=893368de&sv=2) Screenshot of Player in 3D Hex Volume ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#id-2d-hex-area) 2D Hex Area In the 2D version, you just set the Vis Range to determine the size of the hexes surrounding the player: ![Screenshot of Player in 2D Hex Area](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F0qcvcTkQ2Kd0pNYVJ11P%252Fimage.png%3Falt%3Dmedia%26token%3Dfd86a4a5-504f-42ed-86a8-ac2e92880ca5&width=768&dpr=3&quality=100&sign=d296e1dd&sv=2) Screenshot of Player in 2D Hex Area ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#examples) Examples We've included examples with Mirror, in the Examples folder so you can try out both versions: ![Screenshot of Hex Spatial Hash Example folder](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F7XvHgLsnXEcTSvWiN3zw%252Fimage.png%3Falt%3Dmedia%26token%3D561d58e2-ef96-438c-a11e-2b5f7c19f768&width=768&dpr=3&quality=100&sign=a93b3afd&sv=2) Screenshot of Hex Spatial Hash Example folder [PreviousSpatial Hashingchevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing) [NextDistancechevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance) Last updated 3 months ago * [Setting Up](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#setting-up) * [3D Hex Volumes](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#id-3d-hex-volumes) * [2D Hex Area](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#id-2d-hex-area) * [Examples](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing#examples) --- # Cloud Hosting Guides | Mirror During this guide we will set up a dedicated server and place the server build of our project on the dedicated server. **IMPORTANT:** Before we begin, there are some potential problems you may face, as no server is truly 'free': 1. Service providers are NOT free. 2. Most of the time you can start with free trials for a limited time, after x amount of time or x amount of used resources the trial will end and you might incur payment. 3. Always read the providers free trial limitations. 4. Some providers require a payment method for using a Windows instance, however as long as you do not go over the limitations the provider should not bill you. > **NOTE**: Mirror is not affiliated and can not be held responsible for any charges or fees associated with service providers like [AWSarrow-up-right](https://aws.amazon.com/) > , [Microsoft Azurearrow-up-right](https://azure.microsoft.com/en-us/free/) > , [Google Compute Enginearrow-up-right](https://cloud.google.com/compute/) > and others... [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#introduction) Introduction ---------------------------------------------------------------------------------------------------------- During your development with Mirror you will need to test your project as a client and as a server. There are a few possible ways to test your project: 1. Default build: Host/client as one and connecting with another build/editor to the host locally on 1 computer. 2. Server build: Server is a separate executable. You can place it on your computer run it and connect to it as a client. 3. Dedicated Server: Same as the server build but placed on an external machine, you connect to it with the server's external ip. This guide will focus on the "Dedicated Server" option. There are multiple providers and even self hosted dedicated machines. All possibilities still go through the same process to ensure connectivity to clients. A few requirements for a dedicated server: 1. Port forwarding (Not strictly necessary but makes everything a lot easier without needing NAT punchthrough) 2. Firewall exceptions 3. Computer/machine that stays online and accessible whenever you need it. In the upcoming sections we will go through setting up a provider with the free tier. circle-info Always double check that you do not select a paid feature as this is purely meant as a short term period to test out basic functionality during development of your project. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#microsoft-azure) Edgegap We recommend checking our [Edgegap Hosting Guide](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide) for the most convenient way to host your game in the cloud. It doesn't require much setup since the plugin already ships with Mirror. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#microsoft-azure-1) Microsoft Azure Microsoft Azure (as of time of writing) allows setting up a windows instance during the free trial without an active payment method. **To be added** ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#google-compute-engine) Google Compute Engine Google Compute Engine (as of time of writing) does not allow setting up a windows instance during the free trial without an active payment method. **To be added** ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#self-hosted-dedicated-server) Self Hosted Dedicated Server A self hosted dedicated server is the same as the other providers but you provide the hardware, internet connection and costs for running the computer. Most of the time this is the cheapest option during development if you already have an extra machine. Preferably you would put the machine on a different network (to simulate the conditions as the other providers). This would mean you could connect to the machine and put your server build on whenever you need and have access to the router and security settings of the machine for port forwarding and firewall exceptions. In essence, this is the simplest set up but does require extra hardware. [PreviousThe Pragmatic Hosting Guidechevron-left](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide) [NextAWSchevron-right](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws) Last updated 6 months ago * [Introduction](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#introduction) * [Edgegap](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#microsoft-azure) * [Microsoft Azure](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#microsoft-azure-1) * [Google Compute Engine](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#google-compute-engine) * [Self Hosted Dedicated Server](https://mirror-networking.gitbook.io/docs/hosting/server-hosting#self-hosted-dedicated-server) --- # IDs | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/ids#asset-id) Asset Id --------------------------------------------------------------------------------------------- Mirror uses GUID for Asset Ids. Every prefab with a NetworkIdentity component has an Asset Id, which is simply Unity's AssetDatabase.AssetPathToGUID converted to 16 bytes. Mirror needs that to know which prefabs to spawn. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/ids#scene-id) Scene Id --------------------------------------------------------------------------------------------- Mirror uses uint for Scene Ids. Every game object with a NetworkIdentity in the scene (hierarchy) is assigned a scene id in OnPostProcessScene. Mirror needs that to distinguish scene objects from each other, because Unity has no unique id for different game objects in the scene. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/ids#network-instance-id-aka-netid) Network Instance Id (aka NetId) ----------------------------------------------------------------------------------------------------------------------------------------- Mirror uses uint for NetId. Every NetworkIdentity is assigned a NetId in NetworkIdentity.OnStartServer, or after spawning it. Mirror uses the id when passing messages between client and server to tell which object is the recipient of the message. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/ids#connection-id) Connection Id ------------------------------------------------------------------------------------------------------- Every network connection has a connection id, which is assigned by the low level Transport layer. Connection id 0 is reserved for the local connection when the server is also a client (host) [PreviousAuthoritychevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/authority) [NextAttributeschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/attributes) Last updated 5 years ago * [Asset Id](https://mirror-networking.gitbook.io/docs/manual/guides/ids#asset-id) * [Scene Id](https://mirror-networking.gitbook.io/docs/manual/guides/ids#scene-id) * [Network Instance Id (aka NetId)](https://mirror-networking.gitbook.io/docs/manual/guides/ids#network-instance-id-aka-netid) * [Connection Id](https://mirror-networking.gitbook.io/docs/manual/guides/ids#connection-id) --- # Distance | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance#distance-interest-management) Distance Interest Management ------------------------------------------------------------------------------------------------------------------------------------------------------- The straight forward, brute force solution for Interest Management is to simply send all entities to all connections within range. This is what **Network Proximity Checker** did: Copy foreach spawned entity: foreach connection: if (Vector3.Distance(spawned, connection) < visRange): connection.Send(spawned); The only downside is that it's relatively expensive to check every entity against every connection. So if you need loads of entities or connections, it would be smart to use a faster algorithm like [**Spatial Hashing**](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing) . ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance#setting-up) Setting Up Add the **Distance Interest Management** component to the same object as your **Network Manager**: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FZVgewjg9dxzc039ryUbU%252Fimage.png%3Falt%3Dmedia%26token%3D770ee10d-556e-477c-b631-3535b64f489b&width=768&dpr=3&quality=100&sign=7ffc283c&sv=2) The **Vis Range** defines the radius around a player from which it receives world updates. The **Rebuild Interval** is in seconds, and determines how often Mirror recalculates visibility of objects to clients. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance#custom-visible-range) Custom Visible Range The Vis Range setting above applies to all networked objects as the "default" range. You can override this value on objects that need a different range, e.g. exception cases for things that are very large or very small, relative to most other things in the scene. To do this, just add a **Distance Interest Management Custom Range** component to those objects and set the Vis Range values for those objects according to your needs. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F5VKDz7jNfSbo6jxIx7Mo%252Fimage.png%3Falt%3Dmedia%26token%3D95be9a49-0070-447d-a723-ce31bf900c82&width=768&dpr=3&quality=100&sign=5f05043d&sv=2) [PreviousHex Spatial Hashingchevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing) [NextScenechevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene) Last updated 4 years ago * [Distance Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance#distance-interest-management) * [Setting Up](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance#setting-up) * [Custom Visible Range](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance#custom-visible-range) --- # Time Synchronization | Mirror For many algorithms you need the clock to be synchronized between the client and the server. Mirror does that automatically for you. To get the current time use this code: Copy double now = NetworkTime.time; It will return the same value in the client and the servers. It starts at 0 when the server starts. Note the time is a double and should never be cast to a float. Casting this down to a float means the clock will lose precision after some time: * after 1 day, accuracy goes down to 8 ms * after 10 days, accuracy is 62 ms * after 30 days , accuracy is 250 ms * after 60 days, accuracy is 500 ms Mirror will also calculate the RTT(round trip time) as seen by the application: Copy double rtt = NetworkTime.rtt; You can measure accuracy. Copy double time_standard_deviation = NetworkTime.timeSd; for example, if this returns 0.2, it means the time measurements swing up and down roughly 0.2 s Network hiccups are compensated against by smoothing out the values using EMA. You can configure how often you want the the ping to be sent: Copy NetworkTime.PingFrequency = 2; You can also configure how many ping results are used in the calculation: Copy NetworkTime.PingWindowSize = 10; [PreviousAttributeschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/attributes) [NextData typeschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) Last updated 5 years ago --- # Scene | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#scene-interest-management) Scene Interest Management ---------------------------------------------------------------------------------------------------------------------------------------------- Scene Interest Management is used with Additive Scenes to networked objects to subscenes with physics isolation. That means that even if you have several instances of the same subscene loaded on the server, collisions and such between objects only happen within that subscene without interfering with others. circle-info Server and connected clients always have the same main scene loaded. With additive scenes, this is typically a container scene, and additive subscenes have the actual scene contents. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#setting-up) Setting Up Add the **Scene Interest Management** component to the same object as your **Network Manager**: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fx4sWntHPV5c7Q9LMRoDu%252Fimage.png%3Falt%3Dmedia%26token%3D86c6e4ad-4f49-48ba-9eef-28ce2a48c17f&width=768&dpr=3&quality=100&sign=e4426f7&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#add-physics-simulator) Add Physics Simulator In each subscene, add an empty game object, and add a **Physics Simulator** component to that. Since additive scenes will be loaded on the server as "[physics scenesarrow-up-right](https://docs.unity3d.com/ScriptReference/PhysicsScene.html) " Unity doesn't simulate physics for them, so this component does that for you in each subscene. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FADAkc1uIaHriZEGJpU4v%252Fimage.png%3Falt%3Dmedia%26token%3De2dce81a-fcf4-41bc-9eca-8481e6f13626&width=768&dpr=3&quality=100&sign=9e607deb&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#environment-content) Environment Content Also in each subscene, create an empty game object called **Environment** with a **Network Identity** and make all static non-networked content to be children of this object. Typically this would include scenery, such as buildings, road meshes and other non-interactive content. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FsxfFjfxds15gysjmMVed%252Fimage.png%3Falt%3Dmedia%26token%3De6bd1749-e9f9-40a5-8d5a-021e4790c6d3&width=768&dpr=3&quality=100&sign=b73e106&sv=2) circle-exclamation Do not put anything under the Environment object that will be networked and/or may be interactive by players, e.g. doors, pickups, kiosks, etc. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#spawning-players) Spawning Players When you instantiate a player or other networked object, Unity doesn't have any built-in mechanism to specify which subscene the object is instantiated to...it's always the active scene, which is our container scene. After instantiating and before spawning the object, call `SceneManager.MoveGameObjectToScene` to move the object into the correct subscene. Once it's spawned it will be visible to clients with player objects in the same subscene. If you move it to another subscene, visibility in both the new and previous subscenes will be updated automatically. circle-info Note that the networked objects are only moved to subscenes on the server. Clients spawn everything in the container scene, and there's no need to move objects to a subscene on the clients, since they only have one subscene loaded at a time. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#raycasting-and-such) Raycasting and Such Physics scenes have a special set of methods for Raycast and such that must be used on the server since the server has the subscenes as physics scenes. You can read about those [herearrow-up-right](https://docs.unity3d.com/ScriptReference/PhysicsScene.html) . On the remote (non-Host) clients, raycasting is done with the normal methods, since the client just merges the additive scene with the container without it being a physics scene. [PreviousDistancechevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance) [NextScene + Distancechevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene-+-distance) Last updated 3 years ago * [Scene Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#scene-interest-management) * [Setting Up](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#setting-up) * [Add Physics Simulator](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#add-physics-simulator) * [Environment Content](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#environment-content) * [Spawning Players](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#spawning-players) * [Raycasting and Such](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene#raycasting-and-such) --- # Gitbook Guide | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#regular-text) Regular Text ------------------------------------------------------------------------------------------------------------------ Regular text can also have [linksarrow-up-right](https://github.com/vis2k/Mirror) . ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#gitbook-important-how-tos) Gitbook Important How To's * Save & Merge: [https://gyazo.com/cc284fcb5ba5087dbdead8579433a591arrow-up-right](https://gyazo.com/cc284fcb5ba5087dbdead8579433a591) * Links to chapters: [https://gyazo.com/37bbe0b8d604594afda60a38d57e23dcarrow-up-right](https://gyazo.com/37bbe0b8d604594afda60a38d57e23dc) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#hints) Hints circle-info Super-powers are granted randomly so please submit an issue if you're not happy with yours. triangle-exclamation Critical messages can be shown too. ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#code) Code hello.sh Copy # Ain't no code for that yet, sorry echo 'You got to trust me on this, I saved the world' ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#formulas) Formulas E\=mc2E = mc^2E\=mc2 ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#quotes) Quotes > _“In the information age, the barriers just aren't there. The barriers are self imposed. If you want to set off and go develop some grand new thing, you don't need millions of dollars of capitalization. You need enough pizza and Diet Coke to stick in your refrigerator, a cheap PC to work on, and the dedication to go through with it. We slept on floors. We waded across rivers.”_ ― **John D. Carmack, Masters of Doom** ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#images) Images ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUREDljSDfZUSRHjWJV%252F-MURFaWo6kwrq2hRVN9c%252Fimage.png%3Falt%3Dmedia%26token%3De7ed051e-0bb0-464a-b40e-563e112fa6b1&width=768&dpr=3&quality=100&sign=b44269ca&sv=2) Image Description (optional) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#tables) Tables UDP TCP Makes people happy. Makes people angry. ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#tabs) Tabs First Tab Second Tab This is the first tab. This is the second tab. ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#task-lists) Task Lists * check Task lists * check Can now * check Be done * As well [PreviousMirror Docker Guidechevron-left](https://mirror-networking.gitbook.io/docs/community-guides/mirror-docker-guide) [NextMirror Brandingchevron-right](https://mirror-networking.gitbook.io/docs/community-guides/mirror-branding) Last updated 5 years ago * [Regular Text](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#regular-text) * [Gitbook Important How To's](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#gitbook-important-how-tos) * [Hints](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#hints) * [Code](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#code) * [Formulas](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#formulas) * [Quotes](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#quotes) * [Images](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#images) * [Tables](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#tables) * [Tabs](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#tabs) * [Task Lists](https://mirror-networking.gitbook.io/docs/community-guides/gitbook-guide#task-lists) --- # Team | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/team#team-interest-management) Team Interest Management ------------------------------------------------------------------------------------------------------------------------------------------- Team Interest Management provides for having networked objects only visible to those on the same Team, using a Network Team component on the player object and as well as networked objects that need to have their visibility restricted to a team. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/team#setting-up) Setting Up Add the **Team Interest Management** component to the same object as your **Network Manager**: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fb8PGFRWYOCEW4q0IYwYc%252Fimage.png%3Falt%3Dmedia%26token%3Df6817d23-62a9-44a6-a8a2-0d9fac22a8bf&width=768&dpr=3&quality=100&sign=473e8&sv=2) Add a **Network Team** component to the player prefab and any other prefabs that will belong to a team. Set the Team ID to the same value at runtime for players / objects on the same team. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FMTv1uGOwHgx3TJ7mBLgb%252Fimage.png%3Falt%3Dmedia%26token%3Dc2b99f2f-385b-4d0b-9396-57dd51f04a51&width=768&dpr=3&quality=100&sign=6a287771&sv=2) Enable **Force Shown** on Player objects so they can be seen by players on other teams. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/team#owner-only) Owner Only By assigning a unique value to Team ID for each player and the objects only that client should see, you can achieve "Owner Interest Management" similar to the former Network Owner Checker. [PreviousMatchchevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/match) [NextCustomchevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom) Last updated 4 years ago * [Team Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/team#team-interest-management) * [Setting Up](https://mirror-networking.gitbook.io/docs/manual/interest-management/team#setting-up) * [Owner Only](https://mirror-networking.gitbook.io/docs/manual/interest-management/team#owner-only) --- # Guides | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides#networking-concepts-overview) Networking Concepts Overview --------------------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides#high-level-scripting-api) High Level Scripting API Mirror is a “high-level” networking library. Using this means you get access to commands which cover most of the common requirements for multiuser games without needing to worry about the “lower level” implementation details. Mirror allows you to: * Control the networked state of the game using a “Network Manager”. * Operate “client hosted” games, where the host is also a player client. * Serialize data using a general-purpose serializer. * Send and receive network messages. * Send networked commands from clients to servers. * Make remote procedure calls (RPCs) from servers to clients. * Send networked events from servers to clients. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides#low-level-transport-api) Low Level Transport API Mirror requires a low level [Transport](https://mirror-networking.gitbook.io/docs/manual/transports) to **connect/disconnect/send/recv** messages on a byte\[\] level. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides#engine-and-editor-integration) Engine and Editor integration Mirror’s networking is integrated into the engine and the editor, allowing you to work with components and visual aids to build your multiplayer game. It provides: * A NetworkIdentity component for networked objects. * A NetworkBehaviour for networked scripts. * Configurable automatic synchronization of object transforms. * Automatic synchronization of script variables. * Support for placing networked objects in Unity scenes. * Network components [PreviousLegacychevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management) [NextAuthoritychevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/authority) Last updated 5 years ago * [Networking Concepts Overview](https://mirror-networking.gitbook.io/docs/manual/guides#networking-concepts-overview) * [High Level Scripting API](https://mirror-networking.gitbook.io/docs/manual/guides#high-level-scripting-api) * [Low Level Transport API](https://mirror-networking.gitbook.io/docs/manual/guides#low-level-transport-api) * [Engine and Editor integration](https://mirror-networking.gitbook.io/docs/manual/guides#engine-and-editor-integration) --- # Interest Management | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management#interest-management) Interest Management ---------------------------------------------------------------------------------------------------------------------------- When making multiplayer games, the first obvious approach is to simply broadcast the world state to every player. By default, that's what **Mirror** does when you don't use any Interest Management components. Instead of sending the full world state to every player, it's worth considering sending only what's around a player to the player. There are a few major reasons for interest management: * **Scale**: imagine World of Warcraft. Sending the whole world to every single player would be insane. In order to scale to thousands of connections, we need to only send what's relevant to any given player. * **Visibility**: in a MOBA game like DotA/League of Legends, not everyone should see everyone else all the time. A player should only see his own team and monsters around him. Not only that, but players shouldn't see behind walls etc. * **Cheating**: in games like Counter-Strike, players naturally don't see enemies behind walls because the camera wouldn't render them. But if the whole world state is known in memory, then hackers could exploit that by showing players behind a wall anyway. In other words, interest management is almost always a good idea. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management#built-in-systems) Built-in Systems Select the **Network Manager** and add one of the built in Interest Management components. * [**Spatial Hashing**](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing) is the reason why we moved from the legacy **per-Network Identity** system to a **global** system and uses one global **Vis Range** setting that is the same for everything in the scene. * [Hex Spatial Hashing](https://mirror-networking.gitbook.io/docs/manual/interest-management/hex-spatial-hashing) is the newer, highly optimized version of the older Spatial Hashing. * [**Distance**](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance) is a parity replacement for Network Proximity Checker. * [**Scene**](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene) allows for visual and physics isolation across additive scenes. * [**Scene Distance**](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene-+-distance) is a combination of Scene and Distance above. * [**Match**](https://mirror-networking.gitbook.io/docs/manual/interest-management/match) isolates players for non-physics card, board, arcade games. * [**Team**](https://mirror-networking.gitbook.io/docs/manual/interest-management/team) provides for restricting visibility of networked objects to members of a team. This can also be used for owner-only items, replacing **Network Owner Checker**. * [**Custom**](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom) Interest Management provides a template that you can use to create your own system. * [**Legacy**](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management) Interest Management - Deprecated. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management#final-remarks) Final Remarks The new Interest Management API is fairly simple and allows for heavy customization. We walked through it with the distance based example, which is easy to understand. You may have noticed that this is a **global** component, yet all the functions seem to work **locally** around one **Network Identity** at a time. There are two reasons for that: * Our **legacy** Interest Management system worked on a **per-Network Identity** basis (or **locally** if you will). For the global system, we simply moved those functions into one **global** component. * This allows for global solution like **Spatial hashing**, while also guaranteeing feature pararity and easy upgrades from the old systems. * It's really just the old system moved to a different place. Don't fear it :) * Interest Management can be quite complicated with all the spawning and despawning at the right time. Mirror has a whole lot of interest management code in `**NetworkServer**`, which simply calls the three functions above. * The idea is to shield you from all the complexity. All you need to do is worry about **one Network Identity at a time**. That's fairly easy to think about. [PreviousNetwork Owner Checkerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-owner-checker) [NextSpatial Hashingchevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing) Last updated 3 months ago * [Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management#interest-management) * [Built-in Systems](https://mirror-networking.gitbook.io/docs/manual/interest-management#built-in-systems) * [Final Remarks](https://mirror-networking.gitbook.io/docs/manual/interest-management#final-remarks) --- # The Pragmatic Hosting Guide | Mirror Mirror takes care of your multiplayer game code. However, we still need to talk about hosting! circle-check This guide is for those who want to focus on **making games**. Hacking commands into ssh terminals may be fun, but life is short. The **#1 priority** for this guide is **ease of use**, for we must ship our projects! With a near infinite amount of providers & hosting technologies, Linux distributions and locations, it's easy to get confused about what's best for you game. This guide will give you a basic overview. The next chapters serve as in-depth guides for the different hosting methods, depending on which you choose. [hashtag](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#the-pragmatic-hosting-guide) The Pragmatic Hosting Guide ------------------------------------------------------------------------------------------------------------------------------------------------- Here is a brief overview of different hosting technologies, which games they are for, and which providers you could choose from. [hashtag](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#update-edgegap-unity-plugin) Update: Edgegap Unity Plugin 🇨🇦 ------------------------------------------------------------------------------------------------------------------------------------------------------- ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FsxPqFtNnFT3fwTZ9Nzz0%252Fimage.png%3Falt%3Dmedia%26token%3D1d0fb533-f804-42bc-b252-198738a03417&width=768&dpr=3&quality=100&sign=99dd8daa&sv=2) This is the new, modern way to host game servers. The Edgegap Hosting plugin is already in your Mirror folder and allows you to host to the cloud directly from Unity Editor. We wouldn't mention it here if it wouldn't make life easier. circle-check **Edgegap** allows for ultra low latency hosting, managed directly from the Unity Editor. Check out our step by step guide to get started: [Edgegap’s Dedicated Game Server Hosting – Plugin Guide](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide) ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-1.-hosting-on-your-own-computer) **1.) Hosting on your own Computer** After building your game, you could technically host it on your own machine, or let players host it on their machines. However, this comes with several major issues: 1. **Uptime**: your computer would have to run 24/7. 2. **Security**: what if someone finds an exploit, and gets access to your private data? 3. **Performance**: your Computer / Bandwidth / latency may not be good enough. 4. **Latency**: unlike with professionally hosted servers in data centers, Player to Player connections usually come with quite some latency. 5. **Connectivity**: other players usually won't find your game behind your router, firewall, etc. player to player connections are always difficult. circle-exclamation This method is not recommended. _... except for LAN parties, if you still remember those._ ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-2.-player-hosted--relay-nat-punchthrough) **2.) Player Hosted + Relay / NAT Punchthrough** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FDkixJrjCbksvpIhR3oi7%252Fimage.png%3Falt%3Dmedia%26token%3D86c0d1c2-452a-4677-8f68-64d9fa574b13&width=300&dpr=3&quality=100&sign=5aaec910&sv=2) Still, letting players host their own games can be useful. You will save money on server hosting costs and players will create their servers on demand. We just need to solve the connectivity issue. For that, we can combine two tools: * **NAT Punchthrough**: a hacky technique to 'punch a whole' through your router / firewall so that others can connect to your game. This requires one central server for players to connect to **once**. After the initial connect to the central server, your router / firewall will most likely allow outside packets from other players directly. This works about **70% of the time**. * **Relay**: to avoid headaches, you can offer your own (or rent) a Relay server, which basically forwards traffic between players. Instead of talking to each other, your players all talk through a central Relay. This solves our router + firewall issues 100% of the time. However, you'll usually have to pay for bandwidth. Note that **Uptime, Security and Latency** are still not solved here. However, a decent Relay may reduce your latency to be good enough. circle-check **Edgegap**'s [Distributed Relayarrow-up-right](https://edgegap.com/en/platform/distributed-relay) will give you the best latency (paid). [**Epic Relay**arrow-up-right](https://github.com/FakeByte/EpicOnlineTransport) is free, but with higher latency and a pretty bad C# API. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-3.-dedicated-servers) **3.) Dedicated Servers** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FiTObBwEduOhe84JiyEmY%252Fhetzner.png%3Falt%3Dmedia%26token%3Dd557feed-3e16-415a-a22d-2adb07553675&width=300&dpr=3&quality=100&sign=51d635c5&sv=2) This is the old school way of hosting, and probably what most people consider at first. You sign a contract for a physical dedicated server in some datacenter, install your favorite Linux distribution, SSH into it via Terminal, configure it, then launch your server binary and maintain it over time. Dedicated servers **work for all games**. However, they aren't ideal for all games. It's cumbersome to sign & cancel contracts for every extra server. And you still need to pay while you don't use it. **This is best for persistent worlds**: Minecraft, MMORPGs like World of Warcraft and so on. circle-check **Hetzner** is most often recommended. They have great prices and great hardware. **Namecheap** is good too. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-4.-cloud-hosting) **4.) Cloud Hosting** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F9TMoOril8M1TKT6lNaZu%252Fgoogle.png%3Falt%3Dmedia%26token%3D51cbe278-43fc-45e9-ac51-28821efb6440&width=300&dpr=3&quality=100&sign=efdc3aed&sv=2) You may have heard about Amazon AWS, Google Cloud, Microsoft Azure, etc. They offer virtual servers, which you can spin up and remove with just a few clicks without manually signing contracts & canceling them every time. Usage is generally similar to dedicated servers: you configure your machine, pick your Linux distro, upload your server executable and maintain it yourself. However, Cloud Hosting is **significantly more convenient**. You can rent new servers and remove old servers from a UI with just a few clicks. At the end of the month, you are billed for the resources which you have used. You could even configure your server once, and then spin up additional servers based on the same image with just a few clicks. Cloud hosting **works for all games** as well. However, keep in mind that: * Virtual CPUs are ~20% slower than dedicated CPUs. * Pricing is noticeably higher than for dedicated servers. You essentially pay more for extra **convenience**. New servers can be set up with just a few clicks, and once you don't need them anymore you can simply remove them. There's no need to sign contracts & wait for support all the time. If you value convenience, then Cloud Hosting is a good choice over dedicated servers. circle-check **Google Cloud**, **Amazon AWS** and **Microsoft Azure** are the most popular choices. You will find hosting guides for each one in our documentation. At Mirror we use Google Cloud for our CCU tests & Discord Bots. [hashtag](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-5.-orchestration) **5.) Orchestration** ----------------------------------------------------------------------------------------------------------------------------------- ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FUyMCjmjCsqGTHOuZUubg%252Fedgegap.png%3Falt%3Dmedia%26token%3Dee17f3a8-f5b5-4242-9b1b-0d959629871b&width=300&dpr=3&quality=100&sign=8dc3c1fd&sv=2) Orchestration aims to automate hosting for session based games, on demand. If your game suddenly becomes popular, you may need hundreds or thousands of servers at a time. Setting this up manually with dedicated servers is basically impossible, and even with Cloud Hosting it would still require quite a lot of headaches & time, which is probably better spent on your game itself. Well, good news: orchestration is the future of multiplayer game hosting. In simple terms: 1. You **create a lightweight Docker** image: configure a text file (".Dockerfile") with your Linux distribution, packages, open ports, etc. and then compile your whole project into a "Docker Image". If you aren't familiar with Docker, fear not. It makes your life a **lot** easier. Just learn it once, you'll wind up using it for all your hosting afterwards. No more manually setting up Linux servers, no more apt-get, no more maintenance etc. 2. **Upload your image** to the Orchestration Service. 3. **Configure** your orchestration in a web UI. They will ask you how many servers you want to spawn, when to spawn more, when to remove old servers, etc. [PreviousTankschevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/tanks) [NextCloud Hosting Guideschevron-right](https://mirror-networking.gitbook.io/docs/hosting/server-hosting) Last updated 6 months ago * [The Pragmatic Hosting Guide](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#the-pragmatic-hosting-guide) * [Update: Edgegap Unity Plugin 🇨🇦](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#update-edgegap-unity-plugin) * [1.) Hosting on your own Computer](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-1.-hosting-on-your-own-computer) * [2.) Player Hosted + Relay / NAT Punchthrough](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-2.-player-hosted--relay-nat-punchthrough) * [3.) Dedicated Servers](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-3.-dedicated-servers) * [4.) Cloud Hosting](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-4.-cloud-hosting) * [5.) Orchestration](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide#id-5.-orchestration) --- # 2019 Change Log | Mirror circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-630---2019-dec-09) v6.3.0 - 2019-Dec-09 ------------------------------------------------------------------------------------------------------------------------------------------------- * Added: SyncMode selector now works for components on any scene objects owned by a client in addition to the player object, e.g. pets. * Added: MessageBase now fully supports inheritance. * Added: Room example now has UI button for host to return all clients to the Room scene and other improvements. * Fixed: ReplacePlayerForConnection now works for existing scene objects as long as another player doesn't own the targeted object. * Fixed: isClient and isServer are now true for networked objects in Start and OnStartClient / OnStartServer, respectively. * Fixed: hasAuthority is now set before OnStartClient and OnStartLocalPlayer are invoked. * Changed: connectionToClient is now used to assign client authority. * Changed: In many respects, the Host player acts a lot more like a client and will reveal bugs better. * Changed: ReplacePlayerForConnection now has an optional bool to retain authority of the previous object (default = false). * Removed: `NetworkServer.SpawnWithClientAuthority` is deprecated in favor of overloads of `NetworkServer.Spawn`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-502---2019-nov-03) v5.0.2 - 2019-Nov-03 ------------------------------------------------------------------------------------------------------------------------------------------------- * Added: SyncList and SyncSet custom Equality Comparer support. * Added: Custom serializers may be implemented for any type in Cmd's and Rpc's. * Added: [Fallback Transportarrow-up-right](https://mirror-networking.com/docs/Articles/Transports/Fallback.html) . * Fixed: SyncVar hooks are no longer called in Host if no change. * Fixed: Network Identity no longer throws a null reference exception in RemoveClientAuthority. * Fixed: Server transport now suspended during scene change to prevent erroneous messages. * Fixed: SyncList, SyncDictionary and SyncSet now use a custom IEnumerator to avoid memory allocation. * Fixed: sceneID is no longer reset in certain cases when editing a prefab. * Changed: PreprocessorDefine code moved to CompilerSymbols folder to avoid paradox of missing symbols preventing the symbols being added to the project. * Changed: Host player no longer gets authority assigned to all objects by default. * Changed: Commands no longer bypass serialization for Host player, making debugging easier. * Changed: Local connections now maintain their own message queue. * Changed: Transport.Available is now abstract. * Removed: Network Identity: Local Player Authority has been removed as no longer necessary. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-407---2019-oct-03) v4.0.7 - 2019-Oct-03 ------------------------------------------------------------------------------------------------------------------------------------------------- * Added: [Authenticatorsarrow-up-right](https://mirror-networking.com/docs/Articles/Components/Authenticators/index.html) support to authenticate clients in the Connect phase. * Added: Profiler events. These events can be subscribed to by the [Network Profilerarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Profiler.html) to provide visual information. * Added: Transports now include channel in profiler events. * Added: Transport abstract class now supports sending a message to a list of connection id's. * Fixed: SceneMessage now has sceneOperation enum so clients can properly handle additive scenes. * Fixed: NetworkClient handlers are now cleared in Shutdown. * Fixed: Offline scene is no longer reloaded when client fails to connect or is rejected. * Fixed: Start Position Index is now reset to zero when server is stopped. * Fixed: Network Room Players are now all in DontDestroyOnLoad so they don't respawn in the game scene. * Fixed: Network Room example player controller restores main camera on disable. * Fixed: Components with different sync intervals were not sending updates to clients. * Fixed: In certain cases, weaver wouldn't weave some external assemblies. * Fixed: Network Animator now does a full sync for new clients. * Fixed: Network Behaviour inspector now shows SyncMode for private SyncVars. * Fixed: Calling Commands and Rpcs of parent classes from inherited classes works as it should. * Fixed: Telepathy no longer hangs when attempting to connect to a nonexistent host. * Fixed: Websockets Transport now properly returns the client endpoint information via `ServerGetClientAddress`. * Fixed: WebGL build now works with ArraySegment. * Changed: Mirror is now free of garbage memory allocation on the sending side. * Some transports may still have a little garbage allocation yet. * Changed: Deprecated the AddPlayerMessage extraMessage byte\[\] in favor of an easier approach to [Custom Playersarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/GameObjects/SpawnPlayerCustom.html) . * This is a breaking change: The virtual method OnServerAddPlayer loses the AddPlayerMessage parameter. * Changed: `NetworkIdentity.RemoveAuthorityForConnection` is now easier to use: no need to supply the current "owner" anymore. * Changed: Renamed `NetworkConnection.playerController` to `identity` ... see [Deprecationsarrow-up-right](https://mirror-networking.com/docs/Articles/General/Deprecations.html) for details. * Changed: Lobby system renamed to Room to better align the name for what it is and make way for a future Lobby framework. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-3174---2019-sep-04) v3.17.4 - 2019-Sep-04 --------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Custom Network Readers & Writers via extension methods. * Added: Network Sync Mode selector on components to sync to observers (default) or just the owner. * Added: SyncVars now support structs and enums in other assemblies. * Added: Support for reading and writing array segments. * Added: Network Animator now has layers support. * Added: New virtual method OnServerChangeScene to Network Manager. * Added: XML summary comments for intellisense and future generated class docs. * Updated Examples and Documentation. * Fixed: SceneID was not set to 0 for prefab variants. * Fixed: Observers were not properly rebuilt on scene changes. * Fixed: SyncVar hooks were not able to change other SyncVars in Host mode. * Fixed: Telepathy not setting socket options on accepted clients. * Fixed: Catch IL2CPP bug. * Fixed: Telepathy and Websockets now start connections ID's at 1 instead of 2. * Fixed: Websockets support for SSL restored. * Fixed: Network Manager no longer complains about missing player prefab if auto-create is disabled. * Fixed: Removed a garbage allocation in Network Transform. * Fixed: NetworkClient.Ready was being called unnecessarily in certain cases, e.g. SceneMessages. * Changed: Documentation moved to website and API generated docs implemented. * Changed: AddPlayerForConnection handler is now internal to keep safety checks intact. * Changed: A bunch of messages converted to value types for performance. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-3116---2019-jul-10) v3.11.6 - 2019-Jul-10 --------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: Telepathy IPv4, IPv6, and FQDN should all work now. * Fixed: TelepathyTransport error in UWP builds. * Fixed: OnApplicationQuit is handled better now. * Fixed: Performance and memory allocation improvements. * Changed: Telepathy Source is now included instead of a DLL. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-31010---2019-jun-19) v3.10.10 - 2019-Jun-19 ----------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Scene Message now supports params for SceneMode (Normal / Additive) and PhysicsMode (2D / 3D). * Added: ClientScene.Send now has an optional ChannelId parameter. * Added: ASMDEF to Examples folder. * Added: Support for sending and receiving ArraySegment * Added: IReadOnlyList in SyncLists. * Fixed: Network Manager not switching to correct scene in some cases. * Fixed: ListServer Ping not found in WebGL. * Fixed: TelepathyTransport.GetMaxPacketSize uses the new configurable max size. * Fixed: Significant reduction in memory allocation and garbage collection. * Changed: Use transform.localPosition and transform.localRotation for better VR support. * Removed: Websockets send queues (they never worked) and SSL (temporarily because it didn't work). [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-367----2019-apr-28) v3.6.7 -- 2019-Apr-28 --------------------------------------------------------------------------------------------------------------------------------------------------- * Changed: NetworkReader now uses ArraySegment to minimize allocations. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-366----2019-apr-24) v3.6.6 -- 2019-Apr-24 --------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: Reverted two internal refactor commits that had unintended consequences. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-365----2019-apr-23) v3.6.5 -- 2019-Apr-23 --------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: Unity 2019.1 compatibility. * Fixed: Erroneous error indicating prefabs were missing Scene ID's. * Fixed: OnDeserializeSafely now works without allocations. * Fixed: Weaver not writing symbol files, preventing breakpoints from working in Visual Studio. * Fixed: Network Identity SceneID generation now uses RNG Crypto Service Provider. * Fixed: Scene lighting in Additive example. * Fixed: Player Prefab transform details now respected when instantiated in the absence of NetworkStartPosition. * Removed: Tests folder from Unity package generation (no end-user value). [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-359----2019-apr-12) v3.5.9 -- 2019-Apr-12 --------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: Network Manager round-robin mode using NetworkStartPosition objects now uses hierarchy sibling order. * Fixed: IsLocalPlayer is now reliably accurate in `Start()` by combining OwnerMessage and SpawnPrefabMessage. * Fixed: Stack overflow issues with Weaver and Cecil. * Fixed: Corrected assembly paths passed to weaver. * Fixed: Enum bandwidth reduced in SyncVars, Commands, and Rpcs. * Fixed: Placeholder files added for removed code files so updating works better. * Changed: Network Manager `isHeadless` is a static property now, changed from `IsHeadless()`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-353----2019-apr-10) v3.5.3 -- 2019-Apr-10 --------------------------------------------------------------------------------------------------------------------------------------------------- * Fixed: Exceptions in overrides of Network Manager and other components incorrectly silenced. * Fixed: Lobby system sometimes would not spawn and swap game player prefabs into the game scene. * Fixed: Application.targetFrameRate no longer set in host mode. * Changed: Telepathy: Split MaxMessageSize to allow setting a different value for client and server. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-349----2019-apr-6) v3.4.9 -- 2019-Apr-6 ------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Semantic Versioning (which is why we jumped from 1.6 to 3.4.9). * Added: [SyncDictionaryarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Sync/SyncDictionary.html) . * Added: [SyncHashSetarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Sync/SyncHashSet.html) . * Added: [SyncSortedSetarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Sync/SyncSortedSet.html) . * Added: SyncList and SyncDictionary support all IList and IDictionary derived types, respectively. * Added: Documentation for [SyncVarsarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Sync/SyncVars.html) . * Added: Documentation for [SyncEventsarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Sync/SyncEvent.html) . * Added: NoRotation to Network Transform. * Added: Scale is now included in spawn payload along with position and rotation. * Added: Generic `IMessageBase` to allow struct message types. * Added: Weaver now supports Vector2Int and Vector3Int. * Added: List Server example. * Added: Additive Scenes example. * Fixed: SyncLists now work correctly for primitives and structs. * Fixed: SyncVar Hooks now will update the local property value after the hook is called. * You no longer need to have a line of code in your hook method to manually update the local property. * Fixed: Host should not call Disconnect on transports. * Fixed: NetworkAnimimator now supports up to 64 animator parameters. * Fixed: Network Manager `StartServer` no longer assumes scene zero is the default scene...uses `GetActiveScene` now. * Fixed: `NetworkServer.Shutdown` now resets `netId` to zero. * Fixed: Observers are now properly rebuilt when client joins and `OnRebuildObservers` / `OnCheckObserver` is overridden. * Fixed: NetworkProximityChecker: On rare occasion, player could be excluded from observers rebuild. * Fixed: NetworkLobbyPlayer `OnClientReady` works now. * Fixed: NetworkLobbyPlayer Remove button not showing for P1 when Server Only. * Fixed: NetworkLobbyManager `pendingPlayers` and `lobbySlots` lists are now public for inheritors. * Fixed: Offline scene switching now works via `StopClient()`. * Fixed: Pong example updated. * Fixed: Source Weaver was deleting PDB files, preventing breakpoints and debugging from working. * Changed: TargetRpc NetworkConnection parameter is now optional...the calling client's NetworkConnection is default. * Changed: Movement example replaced with Tank example. * Changed: NetworkClient functions are all static now, so the singleton is gone. Use NetworkClient directly. * Changed: SyncList now supports structs directly, making SyncListSTRUCT obsolete. * Removed: SyncListSTRUCT - Use SyncList instead. * Removed: NetworkClient.ShutdownAll is obsolete -- Use NetworkClient.Shutdown instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-16----2019-mar-14) v1.6 -- 2019-Mar-14 ------------------------------------------------------------------------------------------------------------------------------------------------ * Fixed: Websockets transport moved to Mirror.Websocket namespace. * Fixed: Network Animator bandwidth abuse. * Fixed: Network Animator float sync bug. * Fixed: Persistent SceneID's for Networked objects. * Changed: Documentation for [Transportsarrow-up-right](https://mirror-networking.com/docs/Articles/Transports/index.html) . * Changed: Weaver is now full source...FINALLY! * Changed: ClientScene.AddPlayer 2nd parameter is now `byte[] extraData` instead of `MessageBase extraMessage`. * Please refer to the code sample [herearrow-up-right](https://mirror-networking.com/docs/Articles/Guides/GameObjects/SpawnPlayerCustom.html) to see how to update your code. * Changed: Network Manager -- Headless Auto-Start moved to `Start()` from `Awake()`. * Changed: Removed Message ID's for all messages - See [Network Messagesarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Communications/NetworkMessages.html) for details. * Message IDs are now generated automatically based on the message name. * Previously you would call Send(MyMessage.MsgId, message), now you call Send(message). * Removed: Documentation for Groove Transport - use Websockets Transport instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-15----2019-mar-01) v1.5 -- 2019-Mar-01 ------------------------------------------------------------------------------------------------------------------------------------------------ * Added: **Migration Tool** to (mostly) automate conversion from UNet. * Added: Full support for WebSockets and WebSocketsSecure to replace UNet LLAPI. * Added: Transport Multiplexer - allows the use of multiple concurrent transports. * Added: NetworkLobbyManager and NetworkLobbyPlayer with example game. * Added: Configurable Server Tick rate in Network Manager. * Added: New virtual OnClientChangeScene fires right before SceneManager.LoadSceneAsync is executed. * Added: Unit tests for Weaver. * Fixed: Garbage allocations removed from a lot of things (more work to do, we know). * Fixed: NetworkProximityChecker now uses `OverlapSphereNonAlloc` and `OverlapCircleNonAlloc`. * Fixed: SyncVar hook not firing when clients joined. * Fixed: Network Manager no longer assumes it's on Scene(0) in Build Settings. * Fixed: Network Animator no longer limited to 6 variables. * Fixed: TelepathyTransport delivering messages when disabled. * Changed: Minimum Unity version: **2018.3.6** * Removed: SceneAttribute.cs (merged to CustomAttributes.cs). * Removed: `NetworkClient.allClients` (Use `NetworkClient.singleton` instead). * Removed: `NetworkServer.hostId` and `NetworkConnection.hostId` (holdovers from LLAPI). * Removed: `NetworkConnection.isConnected` (Network Connection is always connected). * Removed: `Transport.GetConnectionInfo` (Use `ServerGetClientAddress` instead). [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-14----2019-feb-01) v1.4 -- 2019-Feb-01 ------------------------------------------------------------------------------------------------------------------------------------------------ * Added: HelpURL attributes to components. * Added: Automatic targetFramerate for headless builds. * Added: ByteMessage to Messages class. * Fixed: Connecting state can be canceled properly. * Fixed: Network Transform interpolation applied to client's own object. * Fixed: Objects are spawned with correct rotation. * Fixed: SceneId assignment. * Fixed: Changed syncInterval wasn't saved...it is now. * Fixed: Additive Scene loading. * Changed: **Mirror is now full source** -- no more DLL's. * Changed: **Transports are now components** -- TCP, UDP, WebGL, Steam. * Changed: Transport class now dispatches Unity Events. * Changed: `NetworkServer.SendToClientOfPlayer` uses `NetworkIdentity` now. * Changed: `NetworkServer.SendToObservers` uses `NetworkIdentity` parameter now. * Changed: `NetworkServer.SendToReady` uses `NetworkIdentity` now. * Changed: `NetworkServer.DestroyPlayerForConnection` uses `NetworkIdentity.spawned` now. * Changed: `NetworkConnection.Dispose` uses `NetworkIdentity.spawned` now. * Changed: `NetworkReader.ReadTransform` uses `NetworkIdentity.spawned` now. * Changed: Network Transform reimplemented -- physics removed, code simplified. * Removed: `NetworkClient.hostPort` (port is handled at Transport level). * Removed: `NetworkServer.FindLocalObject` (Use `NetworkIdentity.spawned[netId]` instead). * Removed: `ClientScene.FindLocalObject` (Use `NetworkIdentity.spawned[netId]` instead). [Previous2020 Change Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log) [NextDeprecationschevron-right](https://mirror-networking.gitbook.io/docs/manual/general/deprecations) Last updated 3 years ago * [v6.3.0 - 2019-Dec-09](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-630---2019-dec-09) * [v5.0.2 - 2019-Nov-03](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-502---2019-nov-03) * [v4.0.7 - 2019-Oct-03](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-407---2019-oct-03) * [v3.17.4 - 2019-Sep-04](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-3174---2019-sep-04) * [v3.11.6 - 2019-Jul-10](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-3116---2019-jul-10) * [v3.10.10 - 2019-Jun-19](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-31010---2019-jun-19) * [v3.6.7 -- 2019-Apr-28](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-367----2019-apr-28) * [v3.6.6 -- 2019-Apr-24](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-366----2019-apr-24) * [v3.6.5 -- 2019-Apr-23](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-365----2019-apr-23) * [v3.5.9 -- 2019-Apr-12](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-359----2019-apr-12) * [v3.5.3 -- 2019-Apr-10](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-353----2019-apr-10) * [v3.4.9 -- 2019-Apr-6](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-349----2019-apr-6) * [v1.6 -- 2019-Mar-14](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-16----2019-mar-14) * [v1.5 -- 2019-Mar-01](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-15----2019-mar-01) * [v1.4 -- 2019-Feb-01](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log#version-14----2019-feb-01) --- # Network Profiler | Mirror James Frowen maintains a free Network Profiler that works with Mirror [**here**arrow-up-right](https://github.com/James-Frowen/Mirage.Profiler) . ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F16NhollGrgzMlzVEN3sM%252Fimage.png%3Falt%3Dmedia%26token%3D6ace859a-287f-46fd-99d3-e94959134bdb&width=768&dpr=3&quality=100&sign=2c0f1c41&sv=2) [PreviousNetwork Ping Displaychevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-ping-display) [NextNetwork Rigidbodychevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-rigidbody) Last updated 2 years ago --- # Additive Scenes | Mirror IMPORTANT: Make sure you have a layer in project settings called Player for this example to work well. In Build Settings, remove all scenes and add all of the scenes from the Scenes folder in the following order: * MainScene * SubScene Open the MainScene in the Editor and make sure the Sub Scenes list in the Network Manager component on the Network scene object contains the SubScene scene. This is already setup by default, but if the MainScene was opened and saved before putting the scenes in the Build Settings list, the Sub Scenes list may be cleared accidentally. File -> Build and Run Start up to 3 built instances: These will all be client players. Press Play in the Editor and click Host (Server + Client) in the HUD * This will be the host and the 1st player of up to 4. You can also use Server Only if you prefer. Click Client in the built instances. * WASDQE keys to move & turn your player capsule. * There are objects in the corners of the scene hidden by Proximity Checkers. * The big area in the middle is where the subscene will be loaded when you get near the shelter. * There are also networked objects inside the subscene, also with Proximity Checkers. * Since subscenes are only loaded for individual clients, other clients that are outside the middle Zone won't see what those in the subscene can see. * If you play a built instance as Host or Server and play as client in the editor, you'll see the subscene content load and unload in the hierarchy as you move in and out of the middle Zone. [PreviousAdditive Levelschevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/additive-levels) [NextBasicchevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/basic) --- # Tanks | Mirror This is a simple scene with animated tanks, networked rigidbody projectiles, and NavMesh movement. [PreviousRoomchevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/room) [NextThe Pragmatic Hosting Guidechevron-right](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide) Last updated 4 years ago --- # Authority | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#network-authority) Network Authority --------------------------------------------------------------------------------------------------------------------- Authority is a way of deciding who owns an object and has control over it. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#server-authority) Server Authority Server authority means that the server has control of an object. Server has authority over an object by default. This means the server would manage and control the collectible items, moving platforms, NPCs, and any other networked objects that aren't the player. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#client-authority) Client Authority Client authority means that the client has control of an object. When a client has authority over an object it means that they can call [Commands](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#commands) and that the object will automatically be destroyed when the client disconnects. Even if a client has authority over an object the server still controls SyncVar and control other serialization features. A component will need to use a [Commands](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#commands) to update the state on the server in order for it to sync to other clients. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#how-to-give-authority) How to give authority By default, the server has Authority over all objects. The server can give authority to objects that a client needs to control, like the player object. If you spawn a player object using `NetworkServer.AddPlayerForConnection` then it will automatically be given authority. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#using-networkserverspawn) Using NetworkServer.Spawn You can give authority to a client when an object is spawned. This is done by passing in the connection to the spawn message Copy GameObject go = Instantiate(prefab); NetworkServer.Spawn(go, connectionToClient); circle-info Note: A change of NetworkServer.Spawn hierarchy is not automatically synced. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#using-identityassignclientauthority) Using identity.AssignClientAuthority You can give authority to a client any time using `AssignClientAuthority`. This can be done by calling `AssignClientAuthority` on the object you want to give authority to. You may want to do this when a player picks up an item ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#how-to-remove-authority) How to remove authority You can use `identity.RemoveClientAuthority` to remove client authority from an object. Authority can't be removed from the player object. Instead, you will have to replace the player object using `NetworkServer.ReplacePlayerForConnection`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#on-authority) On Authority When authority is given to or removed from an object a message will be sent to that client to notify them. This will cause the `OnStartAuthority` or `OnStopAuthority` functions to be called. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#check-authority) Check Authority #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#client-side) Client Side The `identity.isOwned` property can be used to check if the local player has authority over an object. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/authority#server-side) Server Side The `identity.connectionToClient` property can be checked to see which client has authority over an object. If it is null then the server has authority. [PreviousGuideschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides) [NextIDschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/ids) Last updated 1 year ago * [Network Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority#network-authority) * [Server Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority#server-authority) * [Client Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority#client-authority) * [How to give authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority#how-to-give-authority) * [How to remove authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority#how-to-remove-authority) * [On Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority#on-authority) * [Check Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority#check-authority) Copy identity.AssignClientAuthority(conn); Copy // Command on player object void CmdPickupItem(NetworkIdentity item) { item.AssignClientAuthority(connectionToClient); } Copy identity.RemoveClientAuthority(); --- # Additive Levels | Mirror The Additive Levels example demonstrates the following: * Using Additive Scenes with Scene Interest Management. * Teleporting between levels via portals and respawning. * Custom Scene Loading with Fade In / Out transition. [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/additive-levels#setting-up) Setting Up --------------------------------------------------------------------------------------------------------------- For this example to work correctly, some setup is required. First, add all the scenes to Build Settings: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FcAcfALdElZFzcRdFqabe%252Fimage.png%3Falt%3Dmedia%26token%3D111af178-6ead-4adb-9874-33595208b48d&width=768&dpr=3&quality=100&sign=a1c61712&sv=2) Build Settings Next, add a Player and Portal Layer to Project Settings under Tags and Layers: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FbXw3X0XMsR5EZ5lC8tqj%252Fimage.png%3Falt%3Dmedia%26token%3Db4abc55b-4f97-4c0f-b992-e357ba83e919&width=300&dpr=3&quality=100&sign=2bcc6f51&sv=2) ... and in Physics settings set the matrix so that Portal only collides with Player: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FyetZmscEdFuDawK1n01F%252Fimage.png%3Falt%3Dmedia%26token%3D734817fd-43e0-4bb7-8ae0-db367632c0d3&width=300&dpr=3&quality=100&sign=9fd399e1&sv=2) Finally, open the Offline scene, and click Play in the editor, and click Host in the HUD. * Player controls are WASD+QE to move and turn. * Move into the Portal in the corner with a scene label over it. Your player will be changed to the other level scene. * Move into the Portal in the corner of the 2nd scene, and your player will be changed back to the first scene If you make a build and start two or more instances (one as Host or Server, the other(s) as clients, and move each one, you'll see that only players in the same level can see and collide with each other. [PreviousExampleschevron-left](https://mirror-networking.gitbook.io/docs/manual/examples) [NextAdditive Sceneschevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/additive-scenes) Last updated 2 years ago --- # Network Animator | Mirror The Network Animator component allows you to synchronize animation states for networked objects. It synchronizes state and parameters from an Animator Controller. Note that if you create a Network Animator component on an empty game object, Mirror also creates a Network Identity component and an Animator component on that game object. * **Client Authority** Enable this to have changes to animation parameters sent from client to server. * **Animator** Use this field to define the Animator component you want the Network Animator to synchronize with. Normally, changes are sent to all observers of the object this component is on. Setting **Sync Mode** to Owner Only makes the changes private between the server and the client owner of the object. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNTjCtCIfNWYw5DqFu%252F-MUNTmj6T4FUcO0cfQ5E%252Fimage.png%3Falt%3Dmedia%26token%3D3916b3d1-6179-4646-bb43-edfe585a56a0&width=768&dpr=3&quality=100&sign=6331dbd9&sv=2) You can use the **Sync Interval** to specify how often it syncs (in seconds). [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-animator#details) Details ------------------------------------------------------------------------------------------------------------ The Network Animator ensures the synchronization of game object animation across the network, meaning that all players see the animation happen at the same. There are two kinds of authority for networked animation (see documentation on [Network Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority) ): > **NOTE:** Animator Triggers are not synced directly. Call `NetworkAnimator.SetTrigger` instead. A game object with authority can use the SetTrigger function to fire an animation trigger on other clients. * If the game object has authority on the client, you should animate it locally on the client that owns the game object. That client sends the animation state information to the server, which broadcasts it to all the other clients. For example, this may be suitable for player characters with client authority. * If the game object has authority on the server, then you should animate it on the server. The server then sends state information to all clients. This is common for animated game objects that are not related to a specific client, such as scene objects and non-player characters, or server-authoritative clients. [PreviousComponentschevron-left](https://mirror-networking.gitbook.io/docs/manual/components) [NextNetwork Authenticatorschevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators) Last updated 5 years ago --- # Network Ping Display | Mirror Network Ping Display shows the Ping time for clients using OnGUI. The Ping time is the moving average of the of the (RTT) Round-trip delay time. RTT is calculated by the PingMessage/PongMessage between the client and server. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_ohYfxSNo9K6EHVa%252F-MUN_psYUOBtBmIisZuK%252Fimage.png%3Falt%3Dmedia%26token%3D3219ffca-af27-40c6-ad37-27a684436819&width=768&dpr=3&quality=100&sign=5a60f362&sv=2) See [Time Synchronization](https://mirror-networking.gitbook.io/docs/manual/guides/time-sync) for more info. [PreviousNetwork Manager HUDchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud) [NextNetwork Profilerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-profiler) Last updated 5 years ago --- # Network Rigidbody | Mirror > The Network Rigidbody classed as "Experimental" for now so please share any problems or bugs you find with it and use at your own risk if production builds. The Network Rigidbody component synchronizes velocity and other properties of a rigidbody across the network. This component is useful when you have a non-kinematic rigidbody that have constant forces applied to them, like gravity, but also want to apply forces or change velocity to that rigidbody or server or client with authority. For example, objects that move and jump using rigidbody using gravity. A game object with a Network Rigidbody component must also have a Network Identity component. When you add a Network Rigidbody component to a game object, Mirror also adds a Network Identity component on that game object if it does not already have one. Network Rigidbody works best when there is also a NetworkTransform for the object to keep position as well as velocity in sync. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNa3ga0d22lPvAl2Ah%252F-MUNa94CYZMF-ffcu5R7%252Fimage.png%3Falt%3Dmedia%26token%3D9354621f-143d-4649-b363-04b1320288dc&width=768&dpr=3&quality=100&sign=dd10caa0&sv=2) By default, Network Rigidbody is server-authoritative unless you check the box for **Client Authority**. Client Authority applies to player objects as well as non-player objects that have been specifically assigned to a client, but only for this component. With this enabled, value changes are send from the client to the server. The **Sensitivity** options allow you to set a minimum thresholds before values are send over network. This helps minimize network traffic for very small changes. For some object you may not want them to rotate but don't need to sync the Angular Velocity. The **Clear Angular Velocity** will set the Angular Velocity to zero each frame causing the minimizing when objects rotation. The same can apply to **Clear Velocity**. If **Clear Velocity Velocity** is enabled then clear is ignored. Normally, changes are sent to all observers of the object this component is on. Setting **Sync Mode** to Owner Only makes the changes private between the server and the client owner of the object. You can use the **Sync Interval** to specify how often it syncs (in seconds). This applies both to Client Authority and Server Authority. [PreviousNetwork Profilerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-profiler) [NextNetwork Lerp Rigidbodychevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-lerp-rigidbody) Last updated 5 years ago --- # Multiple Additive Scenes | Mirror In Build Settings, remove all scenes and add both of the scenes from the Scenes folder in the following order: * Main * Game Open the Main scene in the Editor and make sure the Game Scene field in the MultiScene Network Manager on the Network scene object contains the Game scene. This is already setup by default, but if the Main scene was opened and saved before putting the scenes in the Build Settings list, the Game Scene field may be cleared accidentally. [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/multiple-additive-scenes#multiscene-network-manager) MultiScene Network Manager -------------------------------------------------------------------------------------------------------------------------------------------------------- The MultiScene Network Manager is derived from the base Network Manager and is responsible for additively loading the subscene instances and placing the players in their respective subscene instances and initializing player SyncVars. It has a Game Scene field where the Game subscene is assigned, and an Instances field to set how many instances are loaded on the server. Additionally, the `NetworkManager` object has the [Scene Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management) component. In this example, the subscene instances are additively loaded on the server with `localPhysicsMode = LocalPhysicsMode.Physics3D`. Physics subscenes do not auto-simulate, so each scene has a game object with a generic `PhysicsSimulator` script on it. This script does nothing on the client, only on the server. Clients only ever have one instance of the subscene additively loaded (without `localPhysicsMode`), while server has them all. [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/multiple-additive-scenes#playing-in-the-instances) Playing in the Instances ---------------------------------------------------------------------------------------------------------------------------------------------------- File -> Build and Run Start at least 3 built instances: These will all be client players. Press Play in the Editor and click Host (Server + Client) in the HUD - This will be the host and the 1st player. You can also use Server Only if you prefer. Click Client in the built instances. * WASDQE keys to move & turn your player capsule, Space to jump. * Colliding with the small colored spheres scores points base on their color. * Colliding with the larger tumblers sends them rolling around...they're server-side non-kinematic rigidbodies. * Only scores for the players in the same subscene are shown at the top of the game window. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_nYGVw4QV6-Z3SA8v%252F-MH_nnHcDp2SQ9wpQElM%252Fimage.png%3Falt%3Dmedia%26token%3D80c1244b-746e-43e8-93cf-9aa2c3afee24&width=768&dpr=3&quality=100&sign=e37042c9&sv=2) [PreviousBilliardschevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/billiards) [NextPongchevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/pong) Last updated 4 years ago * [MultiScene Network Manager](https://mirror-networking.gitbook.io/docs/manual/examples/multiple-additive-scenes#multiscene-network-manager) * [Playing in the Instances](https://mirror-networking.gitbook.io/docs/manual/examples/multiple-additive-scenes#playing-in-the-instances) --- # Oracle Free Tier | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier#create-and-configure-your-cloud-machine) Create and configure your cloud machine --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Access the [Oraclearrow-up-right](https://oracle.com/) website. Click on **View accounts**, then click on **Sign up for free Cloud Tier**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0EH-cGDdG3G4Ah_0%252Fimage_01.png%3Falt%3Dmedia%26token%3D208cc4ba-2fc7-40fb-acfd-43874b206e4d&width=768&dpr=3&quality=100&sign=cf956e14&sv=2) Click on **Start for free**, fill out the form, and create your account. Sign in with your Oracle account. If your account is under validation, wait a few minutes before proceeding with the steps. Click on **Set up a network with a wizard**. Select **Create VCN with internet Connectivity**, and click on **Start VCN Wizard**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0K8Yx4_f31NEqQoM%252Fimage_02.png%3Falt%3Dmedia%26token%3D98c0f5b8-d8b4-4dff-956b-e12759f78f4a&width=768&dpr=3&quality=100&sign=7f5b17da&sv=2) Fill in **VCN name** and disable the option **Use DNS hostname in this VCN**, click on **Next**, and wait. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0MWXLRCnO5Tb3dUC%252Fimage_03.png%3Falt%3Dmedia%26token%3D833e26e7-4a27-4cd7-a5e0-b2941bf182ca&width=768&dpr=3&quality=100&sign=8a645158&sv=2) Click on **VCN name** to create rules. Select **Public-Subnet-network**, and then click on **Default Security List for network**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0ODsqNFu63wSj5wy%252Fimage_04.png%3Falt%3Dmedia%26token%3D9c76e27f-8467-4eaf-b54b-ab5da230cdbe&width=768&dpr=3&quality=100&sign=2d064b71&sv=2) Click on **Add Ingress Rules**, and create the following rules for: * Protocol TCP * Port range: 80, 443, and 7777 * Select Stateless option * Protocol UDP * Port range: 80, 443, and 7777 * Select Stateless option ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0QKj7VpyLxpi-Np7%252Fimage_05.png%3Falt%3Dmedia%26token%3D286293ac-3bfc-4a51-8d5c-4466160831b5&width=768&dpr=3&quality=100&sign=f298188b&sv=2) Go to **Homepage** and click on **Create a VM Instance**. Fill out **Computer instance name**, and click on **Edit** in the **Image and shape** group. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0T-zXbsG1zAJjiEY%252Fimage_06.png%3Falt%3Dmedia%26token%3Dc52da76f-cbf3-4c5b-800e-5a1890c2e0a8&width=768&dpr=3&quality=100&sign=74f2799a&sv=2) Click on **Change image**, select **Canonical Ubuntu**, OS Version **18.04**, and click on **Select Image**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0UorWtuuXvodFT0q%252Fimage_07.png%3Falt%3Dmedia%26token%3D99f6fb72-e14d-4756-98c1-f82d395cc52f&width=768&dpr=3&quality=100&sign=2be3b014&sv=2) In the **Network group**, check if the network is the one created in the previous steps. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0WkCXM-iHApyPhS1%252Fimage_08.png%3Falt%3Dmedia%26token%3Dc9941cba-76c3-45ac-ba64-7f92b2d53d9c&width=768&dpr=3&quality=100&sign=f1d2cc9f&sv=2) In **Add SSH Keys**, click on **Save Private Key**. Save this in a safe place; it will be necessary to access your machine. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0ZPuKqqHQiQvGU5N%252Fimage_09.png%3Falt%3Dmedia%26token%3D77e4b3d0-7e9b-4df2-b027-d2758d522899&width=768&dpr=3&quality=100&sign=37b18a48&sv=2) In Boot Volume, you can specify HD Size, or you can use your 100 GB in one machine. Click on Create and wait. Go back to Home, click on **Dashboard** > **Compute** > **Instance**, select your instance, and copy **IP Address**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0_nhOgS_p7hIo7VR%252Fimage_10.png%3Falt%3Dmedia%26token%3Db41b6c27-f0ed-4aa1-b401-b7009ada5085&width=768&dpr=3&quality=100&sign=fbada9b6&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier#access-your-machine) Access your machine ----------------------------------------------------------------------------------------------------------------------------------------- Open the PowerShell editor and type the following command: Example: > If you get an error while trying to connect to your cloud machine, you can fix it by right-clicking on ssh-key, select properties > security > advanced > remove inheritance, and delete all other users, keeping only your Windows user. After you connect, run the following commands to add firewall rules into Ubuntu: Download FileZilla, and follow the steps below to connect to your cloud machine using your ssh-key: [https://filezillapro.com/docs/v3/basic-usage-instructions/ssh-private-keys-for-sftp/arrow-up-right](https://filezillapro.com/docs/v3/basic-usage-instructions/ssh-private-keys-for-sftp/) [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier#create-build) Create Build --------------------------------------------------------------------------------------------------------------------------- In Unity, access **File** > **Build Settings** > **Select Linux** > **Mark Server Build**. Wait for the build to finish, and then upload your files with FileZilla. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MkA-uCR8g4Hk5DQr_El%252F-MkA0e2o0Y4IKUGaOOw5%252Fimage_11.png%3Falt%3Dmedia%26token%3D6cdbbad3-a6ca-4aaf-94ec-fb87053bd13a&width=768&dpr=3&quality=100&sign=ff39e55f&sv=2) This tutorial uses a server folder, but this is optional. Use the following commands: Your server should now be running! [PreviousGoogle Cloudchevron-left](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud) [NextHosting with a Remote Desktopchevron-right](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop) Last updated 1 year ago * [Create and configure your cloud machine](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier#create-and-configure-your-cloud-machine) * [Access your machine](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier#access-your-machine) * [Create Build](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier#create-build) Copy ssh -i [ssh_key_place] ubuntu@[machine_ip] Copy ssh -i c:\users\user\desktop\ssh-key-2021-09-15.key ubuntu@0.0.0.0 Copy sudo apt install firewalld sudo firewall-cmd --zone=public --add-port=7777/tcp --permanent sudo firewall-cmd --zone=public --add-port=7777/udp --permanent sudo firewall-cmd --reload Copy ssh -i c:\users\user\desktop\ssh-key-2021-09-15.key ubuntu@0.0.0.0 cd server chmod +x ./[your_project_name].x86_64 ./[your_project_name].x86_64 --- # Billiards | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FocSm2EdBb5Pu1DChNPJq%252F2023-08-12%2520-%2520Prediction%2520demo.png%3Falt%3Dmedia%26token%3D06d01f5f-033e-4dfb-a725-01f1dc7f4c98&width=768&dpr=3&quality=100&sign=9eb507bc&sv=2) **Mirror** comes with simple multiplayer **Billiards** demo. Mouse drag the white ball to apply force. Billiards is surprisingly easy to implement, which makes this a great demo for beginners! Additionally, this demo will allow us to test `Client Side Prediction` & Reconciliation: * currently, CmdApplyForce is sent to server, and clients see the effect a bit later (latency) * in the future, prediction will show the effect immediately with (ideally) very little corrections The demo is intentionally kept extremely simple without any rules or turns. This way we can apply force and test physics without much wait time. [PreviousBasicchevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/basic) [NextMultiple Additive Sceneschevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/multiple-additive-scenes) Last updated 2 years ago --- # Device Authenticator | Mirror Device Authenticator uses the `SystemInfo.deviceUniqueIdentifier` to identify the client. For platforms that don't support `deviceUniqueIdentifier` a GUID is generated and stored in `PlayerPrefs`. circle-exclamation NOTE: deviceUniqueIdentifier can be spoofed, so there's no guarantee of security. * Drag the Device Authenticator script to the inspector of the object in your scene that has Network Manager * The Device Authenticator component will automatically be assigned to the Authenticator field in Network Manager When you're done, it should look like this: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F9kEOYW3Hkz7XLdd3tahN%252Fimage.png%3Falt%3Dmedia%26token%3Dd781bca1-b6bc-4891-a508-d0977a62ce21&width=768&dpr=3&quality=100&sign=b00fdfa1&sv=2) Network Manager with Device Authenticator assigned ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FccU838ozSQDIyjJNJMMJ%252Fimage.png%3Falt%3Dmedia%26token%3D74113015-08de-4a52-aeed-2fbe4b68559c&width=768&dpr=3&quality=100&sign=3565727b&sv=2) Device Authenticator circle-info You don't need to assign anything to the event lists unless you want to subscribe to the events in your own code for your own purposes. Mirror has internal listeners for both events. [PreviousBasic Authenticatorchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators/basic-authenticator) [NextNetwork Behaviourchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour) Last updated 4 years ago --- # Network Lerp Rigidbody | Mirror > The Network Lerp Rigidbody classed as "Experimental" for now so please share any problems or bugs you find with it and use at your own risk if production builds. The Network Lerp Rigidbody component synchronizes position and velocity of a rigidbody across the network. This component is useful when you have a non-kinematic rigidbody that have constant forces applied to them, like gravity, but also want to apply forces or change velocity to that rigidbody or server or client with authority. For example, objects that move and jump using rigidbody using gravity. A game object with a Network Rigidbody component must also have a Network Identity component. When you add a Network Rigidbody component to a game object, Mirror also adds a Network Identity component on that game object if it does not already have one. When using the Network Lerp Rigidbody you should NOT have NetworkTransform on the same object as the Network Lerp Rigidbody will handle syncing the position By default, Network Lerp Rigidbody is server-authoritative unless you check the box for **Client Authority**. Client Authority applies to player objects as well as non-player objects that have been specifically assigned to a client, but only for this component. With this enabled, value changes are send from the client to the server. Normally, changes are sent to all observers of the object this component is on. Setting **Sync Mode** to Owner Only makes the changes private between the server and the client owner of the object. You can use the **Sync Interval** to specify how often it syncs (in seconds). This applies both to Client Authority and Server Authority. [PreviousNetwork Rigidbodychevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-rigidbody) [NextNetwork Room Managerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager) --- # Client Side Prediction | Mirror ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FYZTaUZhFRkGdzi0F3NVH%252F2024-03-21%2520-%252012-13-11%25402x.png%3Falt%3Dmedia%26token%3Dc976e3a6-a058-420b-8050-29744a12f2ba&width=768&dpr=3&quality=100&sign=998d45d6&sv=2) Billiards is the perfect example to learn about Prediction. circle-exclamation Mirror is currently experimenting with various Prediction algorithms. This is all purely experimental, we don't recommend using this just yet. Let's walk through why we even need prediction, how it works, how we implemented it and what you can use it for in your game **today**. circle-info Please read until the end to understand the **back story** of our Prediction algorithm! [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#why-we-need-prediction) Why we need Prediction --------------------------------------------------------------------------------------------------------------------------------------------- First things first: let's try Billiards **without prediction** to see why we need it! * Open the **Examples/Billiards** demo * Ensure NetworkManager -> LatencySimulation adds some latency (50ms) * Build it, select **Server Only** * Play in Editor, select **Client** to connect to your build * Click and drag the white ball to apply a force You **should** feel a noticeable **delay** from applying force to seeing the physics respond! Emphasis here is on _"__**should feel"**_: if this is not a problem in your game, then you **don't need prediction!** For example, there were many popular MMOs in the 2000s where you simply had to wait for inputs and that was okay. The same is true for card games, strategy games and perhaps even most games in general - it's often okay to wait 50ms. However - for fast paced games like shooters, VR, or even simple physics games like Billiards - having a noticeable delay can be completely unacceptable. As you may have guessed, there is a solution and it's called Prediction! circle-info Prediction means simulating actions on the client immediately in order to avoid delay. Once the server state comes back, we compare the prediction and correct it if necessary! If that definition confuses you, let's explain it again in more detail. Usually, this is what happens when the client wants to apply force to a billiards ball: * Client sends `[Command] CmdApplyForce(force)` to server (... this takes 50 ms) * Server executes `Rigidbody.AddForce(force)` * Server syncs new Rigidbody positions to client (... this takes 50 ms) * Client sees the result, in this case 50ms + 50ms = 100 ms later Now we might think, okay, let's just apply the force on the client immediately: * Client executes `Rigidbody.AddForce(force)` * This happens locally, neither the server nor other clients see it 😭 Okay so, what if we apply the force locally AND sync it to server: * Client executes `Rigidbody.AddForce(force)` * Client sends `[Command] CmdApplyForce(force)` to server (... this takes 50 ms) * Server executes `Rigidbody.AddForce(force)` as well * Everyone is happy... right? Wrong! 😥 Unfortunately, most Physics engines (including Unity's PhysX) are **not deterministic**. Which means that applying force on client will give slightly different results on the server. And those difference very quickly add up to the point where the balls are completely out of sync about half a second later. Yep, this sucks. The reason for it is that 'floating-point' operations aren't deterministic. If we calculate `Rigidbody.position += Vector2.up` on two different machines, we get ever so slightly different results. This difference adds up to massive desync in just under a second. Now you may think: why don't we use **deterministic Physics** engines then? Well for one, because Unity just doesn't have one. And secondly, it's a lot of work to build one. And third, it's slower than regular physics since instead of floating-point numbers, we need fixed-point numbers which effectively need twice as many operations. So, the next question is, what's the solution then? If client should simulate immediately but client and server always drift apart, then what can we do? Well, the easiest solution would be this: * Client executes `Rigidbody.AddForce(force)` * Client sends `[Command] CmdApplyForce(force)` to server (... this takes 50 ms) * Server executes `Rigidbody.AddForce(force)` as well * Server syncs new Rigidbody positions to client (... this takes 50 ms) * Client compares positions and hard corrects its own simulation if necessary. Notice how there's two "... it takes 50 ms" in there! The client has already moved on and now it suddenly gets server state that's 50 + 50 = 100 ms old. Correcting to this state would have to major issues: 1. The state is from 100 ms ago. The client's current state would pretty much always be elsewhere already, causing corrections all the time. 2. The corrections would set it to where it was 100 ms ago, meaning the balls would always jump noticeably backwards every time. So, what's the solution then? Well, it's actually quite simple in theory. The client just needs to store a history of positions: * Client executes `Rigidbody.AddForce(force)` * _(Client saves Rigidbody.position every 50 ms for comparisons later)_ * Client sends `[Command] CmdApplyForce(force)` to server (... this takes 50 ms) * Server executes `Rigidbody.AddForce(force)` as well * Server syncs new Rigidbody positions to client (... this takes 50 ms) * Client compares with the Rigidbody's positions 50+50=100 ms ago! * If there's a mismatch, then do the corrections. As result, it doesn't matter if we got the server state 50ms, 100ms or 150 ms later. The client just checks in history \[- 100 ms\] and compares! Visualized, it may look like this, where the white boxes are the history of positions: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FxAA0bjvtBGbS9hMTdNqj%252F2024-03-21%2520-%252013-15-30%25402x.png%3Falt%3Dmedia%26token%3Df5c255d7-8c86-4ace-999f-9a3cdaaccd1f&width=768&dpr=3&quality=100&sign=9fabd355&sv=2) Okay now, we are almost there. **The last question is: how do we apply corrections?** Currently we change the position where it was 100 ms ago. But how do we make it have an effect on where the billiards ball is **right now**? Well, how about this: we apply the deltas. If the ball was at (1,2,0) before, and has since moved a bit forward and a bit to the right - then correct it to something like (1.1, 2, 0) and then move it 'a bit forward' and 'a bit to the right' on top of it again. To summarize: circle-check Prediction works by **keeping** a history, **correcting** the past and **rewinding** the deltas on top. If none of this makes any sense, no worries. You don't actually have to do any of this yourself. As usual, Mirror takes care of everything for you! Anyway, let's try it in action then! [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#predicted-billiards) Predicted Billiards --------------------------------------------------------------------------------------------------------------------------------------- Now that we understand what Prediction is and how it works, let's actually try it right now! * Open the Examples/**BilliardsPredicted** example from latest Mirror on **GitHub**. * The Asset Store Mirror version may have this demo, but it's not up to date yet as of March 2024. Please grab it from [GitHub Releasesarrow-up-right](https://github.com/MirrorNetworking/Mirror/releases) . * Build it, select **Server Only** in the build, and **Login** the client in your Unity Editor. * Click and drag the white ball to apply a shot to it. * Notice how physics react **instantly** without any latency. * Try increasing the latency in our [Latency Simulation](https://mirror-networking.gitbook.io/docs/manual/transports/latency-simulaton-transport) component to 50ms. * Build and try again - even with latency, reactions are instant! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fg1pwCEIKzI4GOLXjqwXO%252F2024-03-21%2520-%2520Predicted%2520Billiards%2520Release.png%3Falt%3Dmedia%26token%3D109227f5-3dd1-49a4-8874-c9cc9958d52e&width=768&dpr=3&quality=100&sign=b181b889&sv=2) Did you notice the transparent ghost objects? When using PredictedRigidbody, there are always: * **The (transparent) predicted physics object:** this is the Rigidbody which predicts ahead and has corrections applied to it. * The **(rendered)** original object: this is 'your' original object without physics. This is what the player sees. It automatically follows the physics object but with some smoothing applied. * The **(transparent)** remote state object: this is for debugging. It shows you the latest server state of the object. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#adding-predictedrigidbody-to-your-game) Adding PredictedRigidbody to your game ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you want to add prediction to the networked Rigidbodies in your game, it's super easy! **First**, Add the **PredictedRigidbody** component to your prefab: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FTgWobP2DmVS4OnKloJ31%252F2024-03-21%2520-%252013-48-29%25402x.png%3Falt%3Dmedia%26token%3D138be09f-24af-4772-ac2f-68cf7d1ecb06&width=768&dpr=3&quality=100&sign=f5b0b493&sv=2) **Second**, simulate physics on client **AND** send the command to the server: **Third**, simulate physics on server **INSIDE** the command: And that's all! `PredictedRigidbody` takes care of all the magic for you! triangle-exclamation But wait, there's _one more thing... we need to understand_ _**Prediction Mode**__!_ [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#smoothing-mode) Smoothing Mode ----------------------------------------------------------------------------------------------------------------------------- ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FSctjjHRztq92kkVKyv2T%252F2024-03-28%2520-%252022-14-15%25402x.png%3Falt%3Dmedia%26token%3D73dca464-99f2-46f7-80e6-5384364d4322&width=768&dpr=3&quality=100&sign=a4cbae9c&sv=2) Prediction & corrections are always hard applied to the Rigidbody. In order to smooth out results & jitter, there are two different ways for motion smoothing: * **Smooth**: once the Rigidbody starts moving, all the physics components (Rigidbody+Colliders) are automatically moved onto an invisible Ghost object. The Renderer stays on the original object and smoothly interpolates behind the Ghost object. This gives very smooth results, but there's the extra cost of creating & destroying ghosts and smooth following them. * **Fast**: here everything remains on the original GameObject. Renderers are always where physics are. This looks snappier, a bit harsher, less smooth. However, it's also significantly faster. circle-check We are still evaluating both modes for different demos & game projects. The goal is to settle with one mode eventually. The best way to get a feeling for both modes is to try them in our **BilliardsPredicted** demo yourself. Just change them on both prefabs and see the differences. If you choose **Smooth** mode, then the rest of your game needs to prepare for the fact that the object's Rigidbody+Colliders are moved out of and back into the object all the time. Do what we explain below to make this work seemlessly - in fact, if you do it all the time then you can easily switch modes without breaking things. If you don't want to do any of these changes, then just stick with **Fast** mode. Alright so the solution is to just grab the Rigidbody from our PredictedRigidbody component all the time: Yep, this is actually it. Everything you need are 4 lines of code and 1 component! Just to repeat this one more time: It's important to understand that once you add PredictedRigidbody with **Smooth Mode** to an object, it will automatically separate the Rigidbody & Colliders into a Ghost object while predicting! triangle-exclamation Please keep this in mind. `GetComponent()` won't always be available while predicting. `GetComponent()` won't always be available while predicting. `OnCollisionEnter/Exit()` won't always be called while predicting. `OnTriggerEnter/Exit()` won't always be called while predicting. You probably won't need this yet, but for the future if you want to get OnCollision callbacks to work: Just check the **PredictedBilliards** example's code - it's not actually too difficult! [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#predicting-other-types) Predicting other Types --------------------------------------------------------------------------------------------------------------------------------------------- This article focuses on `PredictedRigidbody` - which is a complete component that just works - but only for Rigidbodies. If you want to predict other types like CharacterControllers, there's good news and bad news: * The **Good News** is that the underlying Prediction & Correction algorithms are kept generic. You can find them in Prediction.cs and use them for other types easily. * The **Bad News** is that they are just standalone algorithms. If you want to make an easy-to-use component like PredictedCharacterController, then it's still a bit of work on top of it. We recommend you check out the code in PredictedRigidbody.cs to get a feeling for the separation between high level component and low-level algorithm, and to see how much extra work is needed to predict a specific type like Rigidbody. To summarize: you _can_ use Mirror's prediction for other types, but you _will_ have to do some work. For what it's worth, the hard part (the algorithm) works and comes with heavy test coverage! [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#mirrors-prediction-for-large-physics-scenes) Mirror's Prediction for Large Physics Scenes ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Now there's one last detail that you absolutely must understand about Mirror's prediction. Traditionally, Prediction algorithms always roll back and resimulate **the whole physics scene.** Because if we want to resimulate a `Rigidbody`, obviously we need `Physics.Simulate()`: While this is the most **correct** solution for prediction, there is a downside: performance. Re-simulating large physics scenes multiple times per correction is super expensive! While this gives the best results, it's very CPU heavy and doesn't scale well to large scenes. This is **not** what Mirror does! circle-check Mirror's prediction runs without `**Physics.Simulate()**`. Yes, you read that right! But nothing is for free, so let's keep reading first... Mirror's Prediction was developed in collaboration with a game studio aiming to build networked physics scenes with thousands of predicted Rigidbodies. Using **Physics.Simulate()** was never an object for our implementation since it would not scale, so we had to be creative. At first we thought: there is no way to scale prediction to that many objects. But there was a catch: while the scene has thousands of predicted Rigidbodies, only a few of them are interacted with at any give time by the local player. For example, in most games you may grab a bottle or kick ladder down, but you rarely interact with thousands of Rigidbodies at the same time. While there are games where interacting with thousands of Rigidbodies is necessary (i.e. destruction type games), this was not the case here. So we thought: why don't we try to manually resimulate individual Rigidbodies without using PhysX! While we didn't believe it was going to work, we didn't have a choice. So, we set out to try it anyway. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#history) History --------------------------------------------------------------------------------------------------------------- We started with a very simplified example that's mostly in 2D: predicted Billiards - the example that you can find in your Mirror folder today. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FKbMgzzzaRwK5sWm7ZQIZ%252F2024-03-21%2520-%252014-46-53%25402x.png%3Falt%3Dmedia%26token%3D913e0252-1cff-4f16-bd52-d673ba900b68&width=768&dpr=3&quality=100&sign=ca40f505&sv=2) Specifically, we tried to manually resimulate Rigidbody.position/rotation/velocity/angularVelocity in our C# code, outside of any physics engine. This kinda worked for the first few months, but it never really looked good enough for a production game. But again - we didn't have a choice so we just kept at it. After 4 months of debugging, we managed to fix a few miscalculations, inconsistencies and mis-predictions. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FUg1XGlk7HvkECYbAMbGh%252F2024-03-21%2520-%252014-49-29%25402x.png%3Falt%3Dmedia%26token%3Dfa226620-d214-4bfd-8a8c-0f524e00536c&width=768&dpr=3&quality=100&sign=53bac67b&sv=2) We debugged mispredictions with lots of Gizmos, Debug.DrawLine and stepping through recordings frame by frame. Our Predicted Billiards demo actually ended up working quite well - much better than we anticipated. So it was time to port this to a real game! ... Almost as expected, everything broke and the predictions looked terrible in a more complex scene. But once again, we didn't have a choice so we just kept debugging and painfully fixing one issue after another. In particular, we had to add support for all types of Colliders and Joints, as well as Rigidbodies on child objects. Three months later - and to everyone's surprise - this actually worked really well! Unfortunately we can't show any videos of the game, but just to summarize this once more: circle-check Mirror's prediction works **really well** for **large physics scenes** where the player only **interacts** **with a few objects** at a time. Our algorithm **sacrifices accuracy for performance!** In other words: it works great for the games that we developed it for. It may or may not work for your game, because we still need to test it with more complex physics! [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#worst-case-benchmark) Worst Case Benchmark ----------------------------------------------------------------------------------------------------------------------------------------- Mirror's prediction is optimized for large physics scenes where the player only interacts with a few objects at a time. However, we still built a worst-case benchmark where you can spawn a few hundred (or thousands of) objects that are predicted all the time. We are using this benchmark for profiling and performance optimizations. Feel free to check it out in **Examples/BenchmarkPrediction**, it's probably the easiest prediction example that you'll find! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FiTdDUtj8ccEuYrA7832F%252F2024-03-21%2520-%252019-03-23%25402x.png%3Falt%3Dmedia%26token%3D2f95aec8-fbb5-49a8-93ff-1828e4ca5ec2&width=768&dpr=3&quality=100&sign=7cf0d7c5&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#whats-next) What's Next ---------------------------------------------------------------------------------------------------------------------- After supporting interactable objects, our two major upcoming goals are: * Complex physics with stacked objects * Predicted player movement We are working on predicted stacked objects right now. As of March 2024, they generally sync well, but don't properly come to rest just yet. Just like with the early billiards demos, they don't look good enough for production games just yet! Once they work well, we will release a demo for this too. Predicted player movement has not yet been tested whatsoever. It may or may not work, and we will most likely need to add a 10% tolerance to say: accept 10% of mispredictions instead of hard correcting them always. This is because for players, smoothness while letting them mispredict a little bit should be a worth tradeoff over correcting all the time. Once this works well, we will build a demo! circle-info Not using Physics.Simulate() is a risky approach. It's certainly possible that we will hit a local maximum and can't improve it any further without using Physics.Simulate(). For now, that's not an option. circle-info Prediction will remain our focus for the rest of the year 2024. Let's see where it goes, please try it and report back! 🚀 [PreviousLag Compensationchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/lag-compensation) [NextHistory Boundschevron-right](https://mirror-networking.gitbook.io/docs/manual/general/history-bounds) Last updated 11 months ago * [Why we need Prediction](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#why-we-need-prediction) * [Predicted Billiards](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#predicted-billiards) * [Adding PredictedRigidbody to your game](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#adding-predictedrigidbody-to-your-game) * [Smoothing Mode](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#smoothing-mode) * [Predicting other Types](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#predicting-other-types) * [Mirror's Prediction for Large Physics Scenes](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#mirrors-prediction-for-large-physics-scenes) * [History](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#history) * [Worst Case Benchmark](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#worst-case-benchmark) * [What's Next](https://mirror-networking.gitbook.io/docs/manual/general/client-side-prediction#whats-next) Copy // handle inputs on client void HandleClick() { GetComponent().AddForce(force); // simulate on client CmdAddForce(force); // and let the server know } Copy [Command] void CmdAddForce(Vector3 force) { GetComponent().AddForce(force); // simulate on server } Copy // PROPERLY handle inputs on client void HandleClick() { // Rigidbody access via PredictedRigidbody Rigidbody rb = GetComponent().predictedRigidbody; rb.AddForce(force); // simulate on client CmdAddForce(force); // and let the server know } Copy [Command] void CmdAddForce(Vector3 force) { // on server, this is still fine since Rigidbody always remains on the object GetComponent().AddForce(force); // simulate on server } Copy // for OnCollision, move the code from your predicted object // to the 'other' object instead and grab the original from the collider: void OnCollisionEnter(Collider collider) { // check if the collider is from a predicted object // (which means it may be on the original, or on the ghost object) if (PredictedRigidbody.IsPredicted(collider, out PredictedRigidbody original) { Debug.Log("Collided with {collider} which belongs to {original}"); } } Copy // grab simulation 100 ms ago WorldSnapshot state = history[-100ms]; // compare with server state if (state != serverState) { // resimulate everything state = serverState; Physics.Simulate(); // ... do this again for 50ms ago, 25ms ago, 0ms ago etc. } --- # Attributes | Mirror Networking attributes are added to member functions of Network Behaviour scripts, to make them run on either the client or server. These attributes can be used for Unity game loop methods like **Start** or **Update**, as well as other implemented methods. circle-info **NOTE**: when using abstract or virtual methods the Attributes need to be applied to the override methods too. * **\[Server\]** Only a server can call the method (throws a warning when called on a client). * **\[ServerCallback\]** Same as **Server** but does not throw a warning when called on client. * **\[Client\]** Only a Client can call the method (throws a warning when called on the server). * **\[ClientCallback\]** Same as **Client** but does not throw a warning when called on server. * **\[Command\]** Call this from a client to run this function on the server. Make sure to validate input etc. It's not possible to call this from a server. Use this as a wrapper around another function, if you want to call it from the server too. See also [**Remote Actions**​](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) and [**Data Types**](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) . * **\[ClientRpc\]** The server uses a Remote Procedure Call (RPC) to run that function on clients. See also: [**Remote Actions**](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) **.** * **\[TargetRpc\]** This is an attribute that can be put on methods of Network Behaviour classes to allow them to be invoked on clients from a server. Unlike the ClientRpc attribute, these functions are invoked on one individual target client, not all of the ready clients. See also: [**Remote Actions**](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) . * **\[SyncVar\]** [**SyncVars**](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars) are used to synchronize a variable from the server to all clients automatically. Don't assign them from a client, it's pointless. Don't let them be null, you will get errors. You can use int, long, float, string, Vector3 etc. (all simple types) and Network Identity and game object if the game object has a Network Identity attached to it. You can use [**SyncVar Hooks**](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvar-hooks) to run code on clients when they receive updates from the server. [PreviousIDschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/ids) [NextTime Synchronizationchevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/time-sync) Last updated 4 years ago --- # Hosting with a Remote Desktop | Mirror Please refer to our "[Pragmatic Hosting Guide](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide) " for a modern, best practices hosting method. This guide is about my unusual Remote Desktop hosting approach, without SSH, SCP, Terminal, etc. circle-info This is definitely not best practice, and not light on resources. However, it is very easy to use 😄. Here is a preview of the final result, this is a Google Cloud VM instance, running Debian with a Desktop Environment, which I log into via Google Remote Desktop from my Browser: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FwIqySLWBnWwFt9uQaDJ1%252Fimage.png%3Falt%3Dmedia%26token%3D4bd30aeb-dec4-4ddd-94f5-2aaa7fe77241&width=768&dpr=3&quality=100&sign=c2d4227b&sv=2) A Google Cloud VM instance running with a desktop environment. This allows for the same workflow as my local machine. I can easily navigate the file system, check resource usage, check on long running tasks, download files with Firefox etc. without worrying about terminal commands. Ease of use & convenience are more important to me than a few hundred megabytes of storage. But again, this is not best practice. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop#installation-instructions) Installation Instructions circle-info This guide specifically uses **Google Cloud**, **Debian**, **XFCE** and **Google Remote Desktop**, because this combination was the easiest & most reliable. Feel free to try other methods. This method is based on Google Cloud's official [Guide for using Google Remote Desktoparrow-up-right](https://cloud.google.com/solutions/chrome-desktop-remote-on-compute-engine) on their VM instances. However, with a few recommendations which I figured out over time: * Use at least **15 GB** of disk space. * Use **Debian**. Ubuntu did not work for this method. * A few install **errors are expected**, which is why Google has --fix-broken commands in there. * Use **XFCE** as desktop environment. Cinnamon did not work for this. * It's useful to also install **Firefox**, as mentioned in their guide. After following the Guide, you should be able to log in with [Google Remote Desktoparrow-up-right](https://remotedesktop.google.com/access/) . ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop#extra-file-transfers) Extra: File Transfers Google Remote Desktop's interface has a file transfer feature, which is not that convenient to use. I found it easier to use any of the popular cloud file sync tools. [Megaarrow-up-right](https://mega.nz/) works great for this, because of official Linux support as well as end-to-end encryption. First install it on your local machine with the official download, and create a folder with a test file. Afterwards install it on the cloud server, with the following steps: ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop#summary) Summary We've learned how to install a desktop environment on our cloud server, how to log into it via Google Remote Desktop, and how to transfer files to it. I hope this makes life easier for some of you who aren't that fond of the terminal. We use this method for our Discord Bot (Alan), and a few other tools. You can easily use this for a few game servers as well. But remember, our [Pragmatic Hosting Guide](https://mirror-networking.gitbook.io/docs/hosting/pragmatic-hosting-guide) is better for serious games. [PreviousOracle Free Tierchevron-left](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier) [NextEdgegap’s Dedicated Game Server Hosting – Plugin Guidechevron-right](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide) Last updated 6 months ago * [Installation Instructions](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop#installation-instructions) * [Extra: File Transfers](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop#extra-file-transfers) * [Summary](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop#summary) Copy hostnamectl // to see your debian version // next: use firefox to download the Mega client for Debian 10 sudo apt install /home/USERNAME/Downloads/FILENAME.deb open via applications->system->megasync --- # Unity Canvas HUD | Mirror circle-info Note: A pre-made UI Canvas prefab is now available in Mirror/Examples/Common/CanvasNetworkManagerHUD. [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#end-result) End Result: ------------------------------------------------------------------------------------------------------------------------ ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZl-XMv2Yekz6B8KUYN%252F-MZl-mQ1zYNRnRImEDac%252FCanvas0.jpg%3Falt%3Dmedia%26token%3D67ac44f0-ab55-4213-9cb2-15a5cf3dfe00&width=768&dpr=3&quality=100&sign=82133724&sv=2) A Unity Canvas that covers the majority of the OnGUI NetworkManagerHUDD component features. [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-1) Part 1 --------------------------------------------------------------------------------------------------------------- Blank Project, import Mirror from Asset Store/ Discord Releases unity package. Open up your scene, for this guide we will use Mirror/Examples/Tanks You should be familiar with the examples, and default NetworkManager HUD, they look something like this: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSv8VB7aLddHcXc9dr%252FCanvas1.jpg%3Falt%3Dmedia%26token%3D18d125dc-06b4-4015-9840-167b180461e0&width=768&dpr=3&quality=100&sign=fc8f7a16&sv=2) OnGUI NetworkManagerHUD. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSvHegJdDauAQpe3su%252FCanvas2.jpg%3Falt%3Dmedia%26token%3Da2d07e2e-442d-4ff6-9ed0-029dc407bc14&width=768&dpr=3&quality=100&sign=c51a1e07&sv=2) Mirror/Examples/Tank/Scenes/Scene [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-2) Part 2 --------------------------------------------------------------------------------------------------------------- Create a Canvas in the scene, by either right clicking, UI canvas, or the menu at top, GameObject, UI, Canvas. Set the canvas scaler to “Scale with Screen Size”, this will help with keeping everything same size, on both low and high resolution screens, and is best to set before adding Canvas contents. Then create and attach a new script to the canvas, I have named it CanvasHUD. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSv_NKwIjB9TUG4gOp%252FCanvas4.jpg%3Falt%3Dmedia%26token%3D96da14d2-4f1e-4360-94df-45553ef87b39&width=768&dpr=3&quality=100&sign=98be3d28&sv=2) Scaling. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSvWrtzu54YIapiy2B%252FCanvas3.jpg%3Falt%3Dmedia%26token%3Dca131a49-3ad4-4930-a4bd-596a9663db2a&width=768&dpr=3&quality=100&sign=18ac6389&sv=2) Script. [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-3) Part 3 --------------------------------------------------------------------------------------------------------------- Open up this new script, and open up Mirrors NetworkManagerHUD (for reference). Add the following code as the starting template to CanvasHUD. Create a button inside the main Canvas, and drag it into the Canvas “ButtonHost” variable. We will not focus too much on layout and looks of the canvas for this guide, but go wild and position the contents where you please :) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSvvkhx5dp8TZ3uDOi%252FCanvas5.jpg%3Falt%3Dmedia%26token%3D108b0ca9-5ed6-4908-a708-3f1b82f54b62&width=768&dpr=3&quality=100&sign=6f1f7fe5&sv=2) Simple button. [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-4) Part 4 --------------------------------------------------------------------------------------------------------------- Test! Start the game, and press your own “Host Button”, the game should start. Congratulations, this is the first step to using Unity Canvas with Mirror, and upgrading from the NetworkManagerHUD OnGUI. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSwH8Fr99xjZVttzD0%252FCanvas6.jpg%3Falt%3Dmedia%26token%3Da72f055a-7eb2-4bcd-99b1-98c77e749ad0&width=768&dpr=3&quality=100&sign=c5e2aa3c&sv=2) New canvas button and old OnGUI [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-5) Part 5 --------------------------------------------------------------------------------------------------------------- If you check the old HUD, it can be summarised into 2 parts. The ‘Start’ (before connecting) and ‘Stop’ (after connecting). Create 2 UI panels inside the canvas, rename them Panel Start and Panel Stop, remove the image component from Panel Stop, this way we can tell them apart. Drag your “Button Host” into Panel Start. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSwU2Oq4zNfiREJeGp%252FCanvas7.jpg%3Falt%3Dmedia%26token%3D8bee2ded-0869-4b31-b07c-fa6f4b0937d0&width=768&dpr=3&quality=100&sign=571ea759&sv=2) Before connecting. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSwWY8kh6RcdMNAIqi%252FCanvas8.jpg%3Falt%3Dmedia%26token%3D65ea61d6-3f4d-4110-be31-3d024f78bfb2&width=768&dpr=3&quality=100&sign=77c4ea28&sv=2) After connecting. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSwYw-rmWiUycWiH3s%252FCanvas9.jpg%3Falt%3Dmedia%26token%3D6758b0a0-e451-4103-bed2-5ab66acd785e&width=768&dpr=3&quality=100&sign=9d12175f&sv=2) Summarised sections. [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-6) Part 6 --------------------------------------------------------------------------------------------------------------- Add the following variables to your CanvasHUD script, these variables cover most of what is needed. Next, add more UI ! Exciting right! :D Don’t worry about the code yet, check the image below to see what is needed. Inside “Panel Start” there should be 3 buttons, inputField and optional title text. Panel Stop should contain one button, and 2 texts, you can remove, add, and adjust things after, but for now follow this guide so everything matches up. Drag all the new UI into the CanvasHUD script variables, if you have labelled them all nicely when going along, it will be an easier task. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSwuGDO6xpNYAphBUx%252FCanvas10.jpg%3Falt%3Dmedia%26token%3D127a02ca-b773-4892-9fef-5ba65c7b5315&width=768&dpr=3&quality=100&sign=f0324df8&sv=2) Scene view, Hierarchy layout and script variables. [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-7) Part 7 --------------------------------------------------------------------------------------------------------------- Now for the code to make it all work, various parts will have comments to explain. And this is it, you have now made your own Unity Canvas HUD UI, or upgraded the OnGUI NetworkManagerHUD! :D [PreviousUnity for MMORPGschevron-left](https://mirror-networking.gitbook.io/docs/community-guides/unity-for-mmorpgs) [NextOdin Inspector Supportchevron-right](https://mirror-networking.gitbook.io/docs/community-guides/odin-inspector-support) Last updated 2 years ago * [End Result:](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#end-result) * [Part 1](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-1) * [Part 2](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-2) * [Part 3](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-3) * [Part 4](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-4) * [Part 5](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-5) * [Part 6](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-6) * [Part 7](https://mirror-networking.gitbook.io/docs/community-guides/unity-canvas-hud-guide#part-7) CanvasHUD.cs Copy using Mirror; using UnityEngine; using UnityEngine.UI; public class CanvasHUD : MonoBehaviour { public Button buttonHost; public void Start() { buttonHost.onClick.AddListener(ButtonHost); } public void ButtonHost() { NetworkManager.singleton.StartHost(); } } CanvasHUD.cs Copy public GameObject PanelStart; public GameObject PanelStop; public Button buttonHost, buttonServer, buttonClient, buttonStop; public InputField inputFieldAddress; public Text serverText; public Text clientText; CanvasHUD.cs Copy private void Start() { //Update the canvas text if you have manually changed network managers address from the game object before starting the game scene if (NetworkManager.singleton.networkAddress != "localhost") { inputFieldAddress.text = NetworkManager.singleton.networkAddress; } //Adds a listener to the main input field and invokes a method when the value changes. inputFieldAddress.onValueChanged.AddListener(delegate { ValueChangeCheck(); }); //Make sure to attach these Buttons in the Inspector buttonHost.onClick.AddListener(ButtonHost); buttonServer.onClick.AddListener(ButtonServer); buttonClient.onClick.AddListener(ButtonClient); buttonStop.onClick.AddListener(ButtonStop); //This updates the Unity canvas, we have to manually call it every change, unlike legacy OnGUI. SetupCanvas(); } // Invoked when the value of the text field changes. public void ValueChangeCheck() { NetworkManager.singleton.networkAddress = inputFieldAddress.text; } public void ButtonHost() { NetworkManager.singleton.StartHost(); SetupCanvas(); } public void ButtonServer() { NetworkManager.singleton.StartServer(); SetupCanvas(); } public void ButtonClient() { NetworkManager.singleton.StartClient(); SetupCanvas(); } public void ButtonStop() { // stop host if host mode if (NetworkServer.active && NetworkClient.isConnected) { NetworkManager.singleton.StopHost(); } // stop client if client-only else if (NetworkClient.isConnected) { NetworkManager.singleton.StopClient(); } // stop server if server-only else if (NetworkServer.active) { NetworkManager.singleton.StopServer(); } SetupCanvas(); } public void SetupCanvas() { // Here we will dump majority of the canvas UI that may be changed. if (!NetworkClient.isConnected && !NetworkServer.active) { if (NetworkClient.active) { PanelStart.SetActive(false); PanelStop.SetActive(true); clientText.text = "Connecting to " + NetworkManager.singleton.networkAddress + ".."; } else { PanelStart.SetActive(true); PanelStop.SetActive(false); } } else { PanelStart.SetActive(false); PanelStop.SetActive(true); // server / client status message if (NetworkServer.active) { serverText.text = "Server: active. Transport: " + Transport.active; // Note, older mirror versions use: Transport.activeTransport } if (NetworkClient.isConnected) { clientText.text = "Client: address=" + NetworkManager.singleton.networkAddress; } } } --- # Ready Up And Die! | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#end-result) End Result: ------------------------------------------------------------------------------------------------------------------ 1: To create a “ready up” feature, this will prevent players from moving until server/host says go. 2: An “isDead” player status to create a death and respawn. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaZ0Xz9pMI24iBzXDtZ%252F-MaZ2sDGSFG2Wit4skgK%252FRUAD9.jpg%3Falt%3Dmedia%26token%3D114f1906-0ff2-4528-baca-e99f89848a6d&width=768&dpr=3&quality=100&sign=b6d14fd9&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-1) **Part 1:** -------------------------------------------------------------------------------------------------------------- Blank Project, import Mirror from Asset Store/ Discord Releases unity package. Open up your scene, for this guide we will use Mirror/Examples/Tanks You should be familiar with the examples, if not, have a quick play, build and run, join yourself by having two games on same PC connecting via 'localhost'. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSvHegJdDauAQpe3su%252FCanvas2.jpg%3Falt%3Dmedia%26token%3Da2d07e2e-442d-4ff6-9ed0-029dc407bc14&width=768&dpr=3&quality=100&sign=c51a1e07&sv=2) Mirror/Examples/Tank/Scenes/Scene [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-2) **Part 2:** -------------------------------------------------------------------------------------------------------------- Create a script called SceneScript, due to this guide modifying Mirrors Example scenes, make sure it is in same folder as Tank script. Add this script onto a game object in the scene, also named SceneScript, this will be our canvas to player link as well as our 'scene manager', then attach a NetworkIdentity component, like below. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaYyI6cx2IsRIIvBOqp%252F-MaZ0IW5s8hvIaJcZmHt%252FRUAD3.jpg%3Falt%3Dmedia%26token%3D9ced64ee-c920-43f7-95f4-e6e28d97efbc&width=768&dpr=3&quality=100&sign=b9632f67&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaYyI6cx2IsRIIvBOqp%252F-MaZ0MCQnPmepMAnwrO5%252FRUAD4.jpg%3Falt%3Dmedia%26token%3D855eadee-5405-462e-8779-ef2c2577a322&width=768&dpr=3&quality=100&sign=1296d146&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaYyI6cx2IsRIIvBOqp%252F-MaZ0PcLOF0a8AIq7m8n%252FRUAD5.jpg%3Falt%3Dmedia%26token%3D9f7d011d-c8fe-4ca9-a156-baa4a4b06c8d&width=768&dpr=3&quality=100&sign=cc4dd25c&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-3) **Part 3:** -------------------------------------------------------------------------------------------------------------- Open up this SceneScript.cs, and add the following code, parts will be commented to explain :) [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-4) **Part 4:** -------------------------------------------------------------------------------------------------------------- Now open Tank.cs, this is the guides equivalent to your eventual PlayerScript. And in the Update function, below the isLocalPlayerCheck, add: if (sceneScript.readyStatus != 1) return; This will stop the tanks below code (movement and projectile firing) from running until ready. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaZ0Xz9pMI24iBzXDtZ%252F-MaZ1MIfWi5oaf9ZDrA3%252FRUAD6.jpg%3Falt%3Dmedia%26token%3D9cc47bb0-f54c-483f-a7be-70c33ad99f19&width=768&dpr=3&quality=100&sign=1ed339b7&sv=2) Add the code at the bottom of Tank.cs, after the “RpcOnFire” ends. (But still inside the namespace { } ) [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-5) **Part 5:** -------------------------------------------------------------------------------------------------------------- For this method during death and respawn, rather than destroying the player, we will hide and reshow it. Open up the Tank player prefab, and add the two child objects to the “Objects To Hide” array, “ProjectileMount” is just an empty position marker, and does not need to be added. Upon the sync var change of “isDead”, the hook callback will cycle through this array. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaZ0Xz9pMI24iBzXDtZ%252F-MaZ2XG06ILvKqOC4U6J%252FRUAD7.jpg%3Falt%3Dmedia%26token%3Da01a952c-852c-4ca4-927b-335cb228071d&width=768&dpr=3&quality=100&sign=88f0aba3&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-6) **Part 6:** -------------------------------------------------------------------------------------------------------------- Create a Canvas in the scene, by either right clicking, UI canvas, or the menu at top, GameObject, UI, Canvas. Set the canvas scaler to “Scale with Screen Size”, this will help with keeping everything same size, on both low and high resolution screens, and is best to set before adding Canvas contents. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MZSuZmACdqh9IU0UKUZ%252F-MZSv_NKwIjB9TUG4gOp%252FCanvas4.jpg%3Falt%3Dmedia%26token%3D96da14d2-4f1e-4360-94df-45553ef87b39&width=768&dpr=3&quality=100&sign=98be3d28&sv=2) Create your Unity Canvas UI, with a text, and 3 buttons, label them for easier reference. Here I have placed Status text at top, Server Set Ready button in the middle, and the Die and Respawn buttons to the right. After this set the variables to the correct UI on your SceneScript, like below. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaZ0Xz9pMI24iBzXDtZ%252F-MaZ2wdbT0zcloYG91t9%252FRUAD8.jpg%3Falt%3Dmedia%26token%3D44c8c2cc-a540-4482-9bea-530df3646664&width=768&dpr=3&quality=100&sign=cbd5512f&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-7) **Part 7:** -------------------------------------------------------------------------------------------------------------- Build and Run! Enjoy :) (To help with side by side play testing - Project settings, Player, Resolution and Presentation, Fullscreen Mode to “Windowed”.) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MaZ0Xz9pMI24iBzXDtZ%252F-MaZ2sDGSFG2Wit4skgK%252FRUAD9.jpg%3Falt%3Dmedia%26token%3D114f1906-0ff2-4528-baca-e99f89848a6d&width=768&dpr=3&quality=100&sign=b6d14fd9&sv=2) [PreviousOdin Inspector Supportchevron-left](https://mirror-networking.gitbook.io/docs/community-guides/odin-inspector-support) [NextiOS AppStorechevron-right](https://mirror-networking.gitbook.io/docs/community-guides/ios-appstore-udp) Last updated 2 years ago * [End Result:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#end-result) * [Part 1:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-1) * [Part 2:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-2) * [Part 3:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-3) * [Part 4:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-4) * [Part 5:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-5) * [Part 6:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-6) * [Part 7:](https://mirror-networking.gitbook.io/docs/community-guides/ready-up-and-die#part-7) SceneScript.cs Copy using UnityEngine; using UnityEngine.UI; using Mirror; // For your game, no need to use this namespace, its just for tank example modification :) namespace Mirror.Examples.Tanks { public class SceneScript : NetworkBehaviour { [SyncVar(hook = nameof(OnReadyChanged))] public int readyStatus = 0; void OnReadyChanged(int _Old, int _New) { //this hook is fired when readyStatus is changed via client cmd or directly by host // you dont need to use _New, as the variable readyStatus is changed before hook is called if (readyStatus == 1) { statusText.text = "Server Says Go!"; buttonReady.gameObject.SetActive(false); } // updating our canvas UI SetupScene(); } public Tank playerScript; // this is set by local player, so UI has reference to your player only public Text statusText; public Button buttonReady, buttonDeath, buttonRespawn; private void Start() { //Make sure to attach these Buttons in the Inspector buttonReady.onClick.AddListener(ButtonReady); //you could choose to fully hide the server only buttons from clients, but for this guide we will show them to have less code involved buttonDeath.onClick.AddListener(ButtonDeath); buttonRespawn.onClick.AddListener(ButtonRespawn); } //[ServerCallback] public void ButtonReady() { // you can use the [ServerCallback] tag if server is only ever going to use the function, or do a check inside for if( isServer ) { } if (isServer) { // optional checks to wait for full team, you can add this in connection joining callbacks, or via UI, upto you. //if (NetworkServer.connections.Count > 2) //{ readyStatus = 1; //} //else //{ // playerStatusText.text = "Not enough players."; //} } else { statusText.text = "Server only feature"; } } // For faster prototyping, we will have these as buttons, but eventually they will be in your raycast, or trigger code public void ButtonDeath() { playerScript.CmdPlayerStatus(true); } public void ButtonRespawn() { playerScript.CmdPlayerStatus(false); } public void SetupScene() { if (isServer == false) { buttonReady.interactable = false; } if (readyStatus == 0) { buttonRespawn.interactable = false; buttonDeath.interactable = false; } else if (playerScript) { // quick check to make sure playerScript is set before checking its variables to prevent errors if (playerScript.isDead == true) { buttonRespawn.interactable = true; buttonDeath.interactable = false; } else if (playerScript.isDead == false) { buttonRespawn.interactable = false; buttonDeath.interactable = true; } } } } } Tank Copy public GameObject[] objectsToHide; private SceneScript sceneScript; [SyncVar(hook = nameof(OnChanged))] public bool isDead = false; void OnChanged(bool _Old, bool _New) { if (isDead == false) // respawn { // allow user to kill themselves via button, just for prototyping foreach (var obj in objectsToHide) { obj.SetActive(true); } if (isLocalPlayer) { // Uses NetworkStartPosition feature, optional. this.transform.position = NetworkManager.startPositions[Random.Range(0, NetworkManager.startPositions.Count)].position; } sceneScript.statusText.text = "Player Respawned"; } else if (isDead == true) // death { // have meshes hidden, disable movement and show respawn button foreach (var obj in objectsToHide) { obj.SetActive(false); } sceneScript.statusText.text = "Player Defeated"; } if (isLocalPlayer) { sceneScript.SetupScene(); } } void Awake() { //allow all players to run this, maybe they will need references to it in the future sceneScript = GameObject.FindObjectOfType(); } public override void OnStartLocalPlayer() { // local player sets reference to scene scripts variable, so they can communicate with each other // you could also use regular Start() and if( isLocalPlayer ) { } instead of OnStartLocalPlayer() sceneScript.playerScript = this; sceneScript.SetupScene(); } [Command] public void CmdPlayerStatus(bool _value) { // player info sent to server, then server changes sync var which updates, causing hooks to fire isDead = _value; } --- # Basic Authenticator | Mirror Mirror includes a Basic Authenticator in the Mirror / Authenticators folder which just uses a simple username and password. * Drag the Basic Authenticator script to the inspector of the object in your scene that has Network Manager * The Basic Authenticator component will automatically be assigned to the Authenticator field in Network Manager When you're done, it should look like this: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FCYM10grfIk3nRHtXZ1xU%252Fimage.png%3Falt%3Dmedia%26token%3D0faf412c-4d16-4b06-a921-253c6d91a8d2&width=768&dpr=3&quality=100&sign=d071f53e&sv=2) Network Manager with Basic Authenticator assigned ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FPXZTKUIOm1XW9qs25jtJ%252Fimage.png%3Falt%3Dmedia%26token%3Dfb44fd05-7f76-4a2e-a6b7-df7bd316558b&width=768&dpr=3&quality=100&sign=283d9b76&sv=2) Basic Authenticator * Server Credentials can be set at design time or runtime * Client Credentials would be set at runtime, e.g. from UI input fields, **before** calling `NetworkManager.singleton.StartClient();` circle-info You don't need to assign anything to the event lists unless you want to subscribe to the events in your own code for your own purposes. Mirror has internal listeners for both events. [PreviousNetwork Authenticatorschevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators) [NextDevice Authenticatorchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators/device-authenticator) Last updated 4 years ago --- # 2020 Change Log | Mirror circle-info Mirror uses semantic versioning, and the versions shown here are those that were published to the Asset Store, and occasionally major version bumps happen mid-month between store submissions and are therefore not individually shown here. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-3022----2020-dec-17) [v30.2.2arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v30.2.2) -- 2020-Dec-17 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Network Reader/Writer now does `ReadBlittable` / `WriteBlittable` for better performance. * Added: KCP Transport updated to version 1.4. * Added: Network Authenticator now has `OnStopServer` and `OnStopClient` overrides. * Added: Network Transform now applies compression to rotations. * Added: `SyncVars` now support using types that inherit from `NetworkBehaviour`. * Added: `SimpleWebTransport` now has option for TLS outside the transport. * Added: `MultipleMatches` example featuring Network Match Checker with Lobby and Match functionality. * Fixed: Better presentation of Network Ping Display.. * Fixed: Middleware Transport now listens for inner events correctly.. * Fixed: Calling `StartServer` / `StartClient` more than once is now prevented.. * Fixed: NRE when no host player in `PlayerScore` in `MultipleAdditiveScenes` example. * Fixed: player collisions in `MultipleAdditiveScenes` example. * Fixed: Weaver now properly generates readers and writers for structs in other assemblies, e.g. `Mathematics`. * Fixed: `NetworkServer.maxConnections` is now public. * Fixed: Skip reset of object that's being destroyed. * Fixed: `ReadyStatusChanged` in `NetworkRoomManager` is now public. * Fixed: `NetworkTransform` now correctly uses `ArraySegment` in Commands. * Fixed: Added `OnStopServer` to `NetworkSceneChecker` and `NetworkMatchChecker`. * Fixed: Weaver method lookup conflict with Unity 2020.2. * Fixed: Memory allocation vulnerability in `NetworkReader`. * Changed: Play mode now blocked for invalid scene id's, with error messages. * Changed: Experimental Network Transform now uses `Channels.DefaultUnreliable` and applies compression to rotations. * Changed: Server Only scene objects in examples replaced with normal objects instantiated on server or just eliminated. * **Breaking:** Force `NetworkMessage` to use structs in all cases - classes no longer supported. * **Breaking:** Removed `ReadPacked` / `WritePacked` functions - Use Read and Write variants instead. * **Breaking:** LLAPI has been removed. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-2622----2020-nov-20) [v26.2.2arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v26.2.2) -- 2020-Nov-20 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: [KCP Transportarrow-up-right](https://mirror-networking.com/docs/Articles/Transports/KCPTransport.html) . * Added: [Libuv2k Transportarrow-up-right](https://mirror-networking.com/docs/Articles/Transports/Libuv2k.html) . * Added: Quaternion and float compression. * Added: Option to configure handshakeMaxSize in SimpleWebTransport. * Added: ServerTeleport to Experimental NetworkTransform. * Added: Accept and Reject methods to Authenticator base class for ease of use. * Fixed: Weaver failure on Authenticators and assemblies with only messages and no behaviors. * Fixed: Examples no longer rely on sequential connectionId. * Fixed: Eliminated errors when first importing due to preprocessor defines in transports. * Fixed: Scene ID logging is now consistently in hex format. * Fixed: sceneId when using BuildPipeline.BuildPlayer with incorrect case in path. * Fixed: Trigger not applied correctly for host in NetworkAnimator. * Fixed: Ensure ReadHelper.Read reads exactly number of bytes in SimpleWebTransport. * Changed: Minimum Unity version is now 2018.4.28 LTS. * Changed: Script Templates are now available as a separate package [herearrow-up-right](https://mirror-networking.com/docs/Articles/General/ScriptTemplates.html) . * Changed: Telepathy Transport is now obsolete - Use [KCP Transportarrow-up-right](https://mirror-networking.com/docs/Articles/Transports/KCPTransport.html) instead. * **Breaking:** NetworkIdentity.clientAuthorityCallback is an event now. * **Breaking:** Removed older obsolete methods and tests. * **Breaking:** Transports no longer support sending to a List of connectionIds. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-2303----2020-oct-24) [v23.0.3arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v23.0.3) -- 2020-Oct-24 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Support null when serializing classes. * Added: Support recursive data types. * Added: Support jagged arrays. * Added: New generic Read and Write methods for types used by mirror and user callbacks. * Added: NetworkAnimator now syncs animator.speed. * Added: NetworkTransform Server Teleport function. * Added: New websockets transport: [SimpleWebTransportarrow-up-right](https://github.com/MirrorNetworking/SimpleWebTransport) . * Fixed: ClientScene.localplayer is now set to null when it is destroyed. * Fixed: Fixing IndexChanged hook not being called for NetworkRoomPlayer. * Fixed: Fixing NullReferenceException when loading scene. * Fixed: Fixing NetworkConnectionToClient for IL2CPP. * Fixed: NullReferenceException in tanks example when running in headless server only. * Changed: Use SyncLists/SyncSet/SyncDictionary directly, e.g. `SyncList`, see [Pull Request 2307arrow-up-right](https://github.com/vis2k/Mirror/pull/2307) . * Changed: OnSerialize now includes the component index as byte before serializing each component. Better CPU performance at the cost of bandwidth. * Changed: Can now have 256 NetworkBehaviours per NetworkIdentity. * **Breaking**: Renamed `IMessageBase` to `NetworkMessage`, see [Pull Request 2317arrow-up-right](https://github.com/vis2k/Mirror/pull/2317) . * **Removed**: SyncEvents, see [Pull Request 2178arrow-up-right](https://github.com/vis2k/Mirror/pull/2178) . * **Removed**: Removing manual invoke for Cmd and RPC, see [Pull Request 2223arrow-up-right](https://github.com/vis2k/Mirror/pull/2223) . * **Removed**: Removed Serialize/Deserialize in messages, see [Pull Request 2317arrow-up-right](https://github.com/vis2k/Mirror/pull/2317) . * **Removed**: Removing auto initialize for SyncLists/SyncSet/SyncDictionary, see [Pull Request 2330arrow-up-right](https://github.com/vis2k/Mirror/pull/2330) . * **Removed**: Replacing [Ninja.WebSocketsarrow-up-right](https://github.com/MirrorNetworking/NinjaWebSocketsTransport) with [SimpleWebTransportarrow-up-right](https://github.com/MirrorNetworking/SimpleWebTransport) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1730----2020-sep-04) [v17.3.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v17.3.0) -- 2020-Sep-04 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: NetworkAnimator now syncs Layer Weight. * Added: Lists can now be sent in Command/Rpc/Message/etc. * Added: `[Server]`/`[Client]` can now be used outside of NetworkBehaviour. * Added: Experimental [NetworkLerpRigidbodyarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkLerpRigidbody.html) component that syncs position and velocity and applies them using Lerp. * Fixed: NetworkAnimator now fires triggers immediately on owner. * Fixed: `isServer` will now keep its value after calling `NetworkServer.Destroy`. * Fixed: `[Client]` error message now correctly logs the name of the method. * Fixed: Messages can now be nested within other Message types. * Fixed: `[Server]`/`[Client]` now correctly give error when used on abstract method. * Fixed: Abstract classes can now implement IMessageBase. * Fixed: Weaver now correctly gives error when generating a reader methods for abstract classes. * Changed: NetworkServer no longer runs update if there are no connections. * Changed: NetworkBehaviour.IsDirty is now a public. * Changed: SyncEvent are now obsolete and will be removed in the next version. * **Removed**: isHeadless is now obsolete, Use preprocessor directive `#if UNITY_SERVER` instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1690----2020-aug-01) [v16.9.0arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v16.9.0) -- 2020-Aug-01 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: [NetworkHeadlessLoggerarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkHeadlessLogger.html) log handler that sets console color. * Added: New Mirror List Server, see [Cloud folderarrow-up-right](https://github.com/vis2k/Mirror/tree/master/Assets/Mirror/Cloud) . * Added: Experimental [NetworkRigidbodyarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkRigidbody.html) component that syncs velocity and other rigidbody settings. * Fixed: base method called inside Command/RPC now work if the first base class does not have an override. * Fixed: NetworkRoomPlayer now cleans up roomSlots on disable. * Fixed: Fallback and Multiplex now disable their transports when they are disabled. * Fixed: Websockets transport SocketState now returns false if socket is `undefined`. * Fixed: SyncEvents can now have the same name if they are in different classes. * Fixed: You can now have multiple SyncEvents per class. * Fixed: Message base classes are now processed even if they are declared later in the file. * Fixed: Registering a prefab with and same GUID no longer gives an error. * Fixed: Weaver now generates Serialize methods for classes that implement IMessageBase. * Changed: NetworkProximityChecker now has slightly better performance. * Changed: ClientRpc no longer need Rpc prefix. * Changed: Commands no longer need Cmd prefix. * Changed: TargetRpc no longer need Target prefix. * Changed: NetworkManager.networkSceneName is now protected set as it should not be set directly. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1611----2020-jun-13) [v16.1.1arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v16.1.1) -- 2020-Jun-13 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: \[Command\] now has an `ignoreAuthority` option for invoking Commands on objects the client doesn't have authority over, and Command methods can have an optional `NetworkConnectionToClient sender` parameter. * Added: \[ClientRpc\] now has an `excludeOwner` option to prevent messages from going to the client that owns the object. * Added: Commands and Rpc's can now be declared as virtual and overridden in derived classes. * Added: NetworkLogSettings component and Log Settings Window. * Added: SyncLists now support `AddRange`, `InsertRange`, and `RemoveAll`. * Added: Network Room Manager now has a virtual `OnRoomServerPlayersNotReady` that fires on server from `CheckReadyToBegin`. * Added: Network Room Player template now includes base Network Behaviour overrides. * Added: Network Room Player now has a virtual hook for the index SyncVar, and the override is in the template. * Added: Experimental Network Transform with more control settings and features. * Added: [Network Ping Displayarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkPingDisplay.html) component * Fixed: Network Room Manager.minPlayers is now protected so it's available for derived classes. * Fixed: Network Room Manager no longer does redundant player prefab registration in `OnStartClient`. * Fixed: Network Room Player `OnClientEnterRoom` now correctly only fires on clients. * Fixed: `RegisterClientMessages` was being incorrectly invoked for every scene change. * Fixed: Network Behaviour `SyncMode` and `SyncInterval` was not showing in the inspector in some cases (regression). * Fixed: Network Manager now cleans up network objects better when server stops. * Fixed: Network Manager no longer tries to change to offline scene redundantly in `StopClient`. * Fixed: Network Connection's `lastMessageTime` wasn't being properly initialized, causing incorrect idle timeout disconnects. * Fixed: Websockets transport now correctly pauses and queues messages during scene changes and should otherwise be more stable with SSL * Changed: Improvements were made to the Tanks example. * Changed: Network Room Player now uses virtual SyncVar hook for ReadyStateChanged. * Changed: Network Proximity Checker now uses direct distance check against player objects instead of Physics.SphereCastNonAlloc for better performance. * **Breaking:** Websockets Transport now requires full path to PFX Certificate file. * **Removed**: Discord Transport [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1301----2020-may-06) [v13.0.1arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v13.0.1) -- 2020-May-06 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: [Multiple Concurrent Additive Scenes Examplearrow-up-right](https://mirror-networking.com/docs/Articles/Examples/MultipleAdditiveScenes/index.html) . * Added: [Network Match Checkerarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkMatchChecker.html) component. Use this component to create many concurrent isolated matches within a single game server. * Added: [SyncListsarrow-up-right](https://mirror-networking.com/docs/Articles/Guides/Sync/SyncLists.html) now have Find and FindAll functions. * Added: Network Behaviour now has `OnStopServer` and `OnStopClient` virtual methods. * Added: Weaver now supports custom Reader & Writer for types in other assemblies. * Added: Network Manager now has an optional setting to check for and disconnect remote connections that have gone silent for a specified interval. * Added: Network Server and Network Client now have `ReplaceHandler` methods to avoid warnings when attempting to double register message handlers. * Added: `NetworkServer.SendToAll` now has an optional bool to only send to ready clients, and a `SendToReady` method that doesn't require a Network Identity. * Fixed: Network Animator no longer double-fires SetTrigger / ResetTrigger on the host client. * Fixed: Network Animator is no longer limited to one component per object. * Fixed: Destroy is no longer invoked twice on the server for the player object. * Fixed: `RegisterClientMessages` is no longer invoked twice on the client. * Fixed: Network Behaviour `SyncMode` and `SyncInterval` was not showing in the inspector in some cases. * Fixed: Telepathy Transport - `LateUpdate` now processes a limited amount of messages per tick to avoid deadlocks. * Changed: Network Behaviour: `OnNetworkDestroy` was renamed to `OnStopClient`. * **Breaking:** RemovePlayerMessage has been removed as a potential security risk. Use `NetworkServer.RemovePlayerForConnection` instead. * **Breaking:** Network Behaviour: `OnRebuildObservers`, `OnCheckObserver`, and `OnSetHostVisibility` were moved to a separate class called `NetworkVisibility`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1142---2020-apr-03) [v11.4.2arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v11.4.2) - 2020-Apr-03 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: SyncVar hooks can be virtual now, and overridden in a derived class. * Added: Virtual `OnRoomStopServer` added to Network Room Manager and Script Template. * Added: 10K Networked Objects Benchmark Example. * Fixed: Setting breakpoints in an IDE for Command's and Rpc's work correctly now. * Fixed: `NetworkServer.SendToObservers` now reports correct channel to Mirror Profiler. * Fixed: Network Room Manager's `roomPlayerPrefab` is now `protected` so it can be accessed in derived classes. * Fixed: Network Room Player inspector and documentation updated to be less confusing. * Fixed: Network Identity no longer double calls `NetworkServer.Destroy`. * Fixed: Network Animator now correctly excludes parameters controlled by curves. * Fixed: Network Behaviour now uses a property drawer for the SyncVar label so it displays better. * Fixed: `NetworkServer.SendToReady` overloads are no longer ambiguous. * Fixed: Network Room Manager no longer incorrectly destroys the game player object. It's left in the game scene to be cleaned up by Unity when the scene changes. * Fixed: `StopHost` correctly raises `OnServerDisconnect` in Network Manager, and correctly unwinds before shutting down the server. * Fixed: `isServer` is no longer incorrectly false on server in Network Identity's `OnDestroy`. * Changed: Network Manager `offlineScene` and `onlineScene` store full paths now, so use SceneManager.GetActiveScene().path instead. * Changed: Network Manager HUD now calls `StopHost` / `StopServer` / `StopClient` more appropriately. * Changed: Network Manager HUD labels no longer say LAN. Associated docs also cleaned up to eliminate the misconception of Mirror being LAN only solution. * Changed: Network Transform compression removed and message handling is much simpler now. * Changed: Network Scene Checker initializes in Awake again because `OnEnable` proved to be unreliable in some cases. * Changed: Network Manager will no longer lose references to scenes if they aren't in the Build Settings scene list, however moving or renaming scenes may cause references to be lost. * **Removed:** Many obsolete methods and properties. Use [version 10arrow-up-right](https://github.com/vis2k/Mirror/releases/tag/v10.4.7) first if upgrading from UNet or older Mirror. See [Deprecationsarrow-up-right](https://mirror-networking.com/docs/Articles/General/Deprecations.html) for complete list. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1047---2020-mar-03) [v10.4.7arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v10.4.7) - 2020-Mar-03 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Weaver will now block play mode and builds if there are weaver errors and show them in the console again. * Added: `PooledNetworkReader` and `PooledNetworkWriter`, both Disposable. * Added: `NetworkReader.ReadMessage`. * Added: Network Discovery now handles headless server mode. * Added: SyncVar, Cmd's and Rpc's now support Scriptable Objects via CreateInstance on the receiving side. * Added: Discord Transport _Removed in v16.1.1_ * Fixed: `isClient` now returns true on clients in OnDestroy for networked objects. * Fixed: Host Player race condition for Ready message. * Fixed: Network Animator and Network Transform now correctly check for client authority in their respective Command methods. * Fixed: Network Room Manager Script Template had a virtual method instead of an override. * Fixed: Network Server's calls to NetworkConnectionToClient.Send now includes the channelId parameter that was missing. * Fixed: Network Server's calls to SendToAll, SendToReady, and SendToObservers send to the exact connection if it is detected as local connection, instead of falling back to the .localConnection. * Fixed: Network Server.SpawnObjects returns false if server isn't running. * Fixed: Network Transform rotation detection improved. * Fixed: Weaver generated code now builds properly for IL2CPP (again). * Changed: StartHost in Network Manager is no longer a virtual method (and shouldn't have been). Override OnStartHost instead. * Changed: Network Room Manager's OnRoomServerSceneLoadedForPlayer now includes NetworkConnection parameter. * Changed: Network Scene Checker now works from OnEnable instead of Awake, and uses Scene instead of scene name. * Changed: Renamed NeworkWriter.Write to WriteMessage for consistency. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-902---2020-feb-04) [v9.0.2arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v9.0.2) - 2020-Feb-04 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: Network Animator now has a ResetTrigger function and server / client authority warnings. * Added: Network Transform now has 3 new floats for Sensitivity to quiet down message traffic from micro changes. * Added: Network Observer added to [Script Templatesarrow-up-right](https://mirror-networking.com/docs/Articles/General/ScriptTemplates.html) -- See the new Mirror section in the Assets > Create menu. * Added: [Network Discoveryarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkDiscovery.html) has been reimplemented including an example and script template -- thanks to all those who contributed! * Added: [Network Scene Checker Componentarrow-up-right](https://mirror-networking.com/docs/Articles/Components/NetworkSceneChecker.html) . * Added: Mirror Icon for all components. * Added: Inspector Headers to Network Behaviour, Network Transform, and Network Animator. * Added: URI added to supported data types. * Added: `NetworkReaderPool` has been implemented in place of `new NetworkReader` everywhere, significantly reducing garbage allocation. * Fixed: Network Transform and Network Animator now uses NetworkWriterPool. * Fixed: Network Transform and Network Animator now respect `hasAuthority` for client owned objects. * Fixed: Network Transform will now correctly teleport if time / distance are too large. * Fixed: Network Animator now correctly syncs when clientAuthority is false. * Fixed: Client owned objects are now destroyed when client disconnects (regression). * Fixed: Client authority is now preserved for networked objects carried through scene change in DontDestroyOnLoad (DDOL). * Fixed: Starting server immediately after canceling client connection attempt no longer throws a NRE. * Fixed: IL2CPP builds no longer trigger an assert when stopping server. * Fixed: SyncVars are now set for Host player before hook is invoked. * Fixed: SyncDictionary now correctly updates the value before invoking callbacks. * Fixed: StopHost no longer tries to change to the Offline scene twice. * Fixed: Network Room Manager roomSlots are now correctly managed on both server and clients. * Fixed: Network Room Manager now correctly supports multiple GamePlay scenes and adds a virtual `OnRoomServerAddPlayer`. * Fixed: Additive scene operations no longer incorrectly lead to extraneous AddPlayer messages from clients. * Fixed: `NetworkWriterPool` is now used everywhere instead of `new NetworkWriter` (we missed a couple when the pool was implemented). * Fixed: Patch for Unity 2019.3.x `RequestScriptReload` was moved to EditorUtility from UnityEditorInternal.InternalEditorUtility. * Fixed: Arrays of custom types are now correctly supported. * Changed: Shutdown logic has been streamlined. * Changed: `NetworkIdentity.GetSceneIdenity` method renamed to `GetSceneIdentity` (name typo). * Changed: OnApplicationQuit virtual method added to Transport class and `Transport.activeTransport.Shutdown()` is no longer called from Network Manager. * **Breaking:** SyncVar Hooks now require **two** parameters, one each for the old and new value, and the property value is now set **before** the hook is called. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-677---2020-jan-01) [v6.7.7arrow-up-right](https://github.com/MirrorNetworking/Mirror/releases/tag/v6.7.7) - 2020-Jan-01 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Added: [Script Templatesarrow-up-right](https://mirror-networking.com/docs/Articles/General/ScriptTemplates.html) -- See the new Mirror section in the Assets > Create menu. * Added: Full Text Search added to docs. * Added: Basic Chat example. * Added: Some YouTube videos have been created and linked from various doc pages where appropriate. * Added: Transports can now support using a URI for connection including port. * Added: version.txt file is now included with the release version in it. * Added: Structs that inherit from IMessageBase now generate serializers. * Fixed: Components now appear in docs under API Reference. * Fixed: Delayed disconnect in Basic Authenticator. * Fixed: Multiplexer now handles OnClientConnect and GetMaxMessageSize correctly. * Fixed: Network Room Manager OnRoomServerCreateGamePlayer now includes the Room Player Object as parameter. * Changed: Room example now has Network Room Manager in the Offline scene and correctly switches to the Room scene when server / client is started. * Changed: Network Manager startPositionIndex and loadingSceneAsync are now public. * Changed: SceneMessage now has an optional customHandling flag so devs can handle their own custom scene loading, e.g. using Addressables. * **Breaking:** Network Transform now defaults to server authority and has a Client Authority checkbox. [Previous2021 Change Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2021-change-log) [Next2019 Change Logchevron-right](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log) Last updated 1 year ago * [v30.2.2 -- 2020-Dec-17](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-3022----2020-dec-17) * [v26.2.2 -- 2020-Nov-20](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-2622----2020-nov-20) * [v23.0.3 -- 2020-Oct-24](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-2303----2020-oct-24) * [v17.3.0 -- 2020-Sep-04](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1730----2020-sep-04) * [v16.9.0 -- 2020-Aug-01](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1690----2020-aug-01) * [v16.1.1 -- 2020-Jun-13](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1611----2020-jun-13) * [v13.0.1 -- 2020-May-06](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1301----2020-may-06) * [v11.4.2 - 2020-Apr-03](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1142---2020-apr-03) * [v10.4.7 - 2020-Mar-03](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-1047---2020-mar-03) * [v9.0.2 - 2020-Feb-04](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-902---2020-feb-04) * [v6.7.7 - 2020-Jan-01](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2020-change-log#version-677---2020-jan-01) --- # Network Start Position | Mirror To control where players are spawned, you can use the Network Start Position component. To use these, attach a Network Start Position component to a game object in the scene, and position the game object where you would like one of the players to start. You can add as many start positions to your Scene as you like. The Network Manager detects all start positions in your Scene, and when it spawns each player instance, it uses the position and orientation of one of them. The Network Manager will spawn players at (0, 0, 0) by default. Adding this component to a game object will automatically register/unregister its game object's transform to the Network Manager as an available spawning position. Depending on the Network Manager Player Spawn Method setting the spawning is either Random (possible that the same spawn position will be used by two or more players) or Round Robin (use every available position, until there are more clients than spawn points). ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNatPQ3t278wdLiErJ%252F-MUNavumXS5a7eyiKyVB%252Fimage.png%3Falt%3Dmedia%26token%3Da220375b-2962-44d3-8477-5e471435bd62&width=768&dpr=3&quality=100&sign=83ff54cb&sv=2) [PreviousNetwork Room Playerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player) [NextNetwork Statisticschevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-statistics) Last updated 5 years ago --- # Remote Statistics | Mirror Remote Statistics component allows clients to see servernetwork statistics, which shows cpu, tick/framrate, messages sent and received, amongst other data. Add RemoteStatistics to a players prefab, and the NetworkStatistics to Network Manager. Adjust via the inspector, and see script comments for further details. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FOWP5IwTLWfoJSGSW7nYt%252FScreenshot%25202025-03-23%2520at%252009.30.26.png%3Falt%3Dmedia%26token%3Dcd166f30-ebca-41b5-91c2-346c9615f8b0&width=768&dpr=3&quality=100&sign=61b68b0&sv=2) Attack to Player Prefab ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FbWM8klOsu97cLbkdfNOe%252FScreenshot%25202025-03-23%2520at%252009.28.52.png%3Falt%3Dmedia%26token%3D7129d93a-b200-46b7-bf2a-fd065707fc51&width=768&dpr=3&quality=100&sign=50844ebd&sv=2) Attach to NetworkManager ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FRg7nuD4dga4K61SD6ziL%252FScreenshot%25202025-03-23%2520at%252009.32.27.png%3Falt%3Dmedia%26token%3D8c8700cb-8272-4123-b0d6-29b2c1e47496&width=768&dpr=3&quality=100&sign=72fbfd5b&sv=2) Press key set via inspector, then enter password. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FryGsze0JY7LjeJ0SEJze%252FScreenshot%25202025-03-23%2520at%252009.32.31.png%3Falt%3Dmedia%26token%3D8fb46dd7-9bad-4bf2-b85e-928d4f54aa00&width=768&dpr=3&quality=100&sign=11678202&sv=2) View server stats remotely. [PreviousNetwork Statisticschevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-statistics) [NextNetwork Transformchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-transform) Last updated 1 year ago --- # Network Statistics | Mirror Network Statistics component shows messages and bytes per second sent and received. Add this component to Network Manager object (or any object in an online scene). ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F0nU8Tq8VhmGGe9WP5j98%252Fimage.png%3Falt%3Dmedia%26token%3D74121530-9d0c-4890-b634-bb91b2b128f0&width=300&dpr=3&quality=100&sign=c4d1981b&sv=2) [PreviousNetwork Start Positionchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-start-position) [NextRemote Statisticschevron-right](https://mirror-networking.gitbook.io/docs/manual/components/remote-statistics) Last updated 1 year ago --- # Legacy | Mirror triangle-exclamation Component on this page are **obsolete** and will be removed from future versions of Mirror. Multiplayer games use the concept of network visibility to determine which players can see which game objects at any given time during game play. In a game that has a moving viewpoint and moving game objects, it’s common that players cannot see everything that is happening in the game at once. If a particular player, at a certain point in time during game play, cannot see most of the other players, non-player characters, or other moving or interactive things in your game, there is usually no need for the server to send information about those things to the player’s client. This can benefit your game in two ways: * It reduces the amount of data sent across the network between players. This can help improve the responsiveness of your game, and reduce bandwidth use. The bigger and more complex your multiplayer game, the more important this issue is. * It also helps prevent some cheating. Since a player client does not have information about things that can’t be seen, a hack on that player’s computer cannot reveal the information. The idea of “visibility” in the context of networking doesn’t necessarily relate to whether game objects are directly visible on-screen. Instead, it relates to whether data should or shouldn’t be sent about the game object in question to a particular client. Put simply, if a client can’t ‘see’ an game object, it does not need to be sent information about that game object across the network. Ideally you want to limit the amount of data you are sending across the network to only what is necessary, because sending large amounts of unnecessary data across the network can cause network performance problems. However, it can be also be resource intensive or complex to determine accurately whether a game object truly visible to a given player, so it’s often a good idea to use a more simple calculation for the purposes of determining whether a player should be sent networked data about it - i.e. whether it is ‘Network Visible’. The balance you want to achieve when considering this is between the cost of the complexity of the calculation for determining the visibility, and the cost of sending more information than necessary over the network. A very simple way to calculate this is a distance (proximity) check, and Mirror provides a built-in component for this purpose. [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-proximity-checker-component) Network Proximity Checker Component --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Mirror’s [Network Proximity Checker](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-proximity-checker) component is simplest way to implement network visibility for players. It works in conjunction with the physics system to determine whether game objects are close enough (that is, “visible” for the purposes of sending network messages in your multiplayer game). [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-scene-checker-component) Network Scene Checker Component ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Mirror's [Network Scene Checker](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-scene-checker) component can be used to isolate players and networked objects on the server in additive scene instances. [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-visibility-on-remote-clients) Network Visibility on Remote Clients ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When a player on a remote client joins a networked game, only game objects that are network-visible to the player will be spawned on that remote client. This means that even if the player enters a large world with many networked game objects, the game can start quickly because it does not need to spawn every game object that exists in the world. Note that this applies to networked game objects in your Scene, but does not affect the loading of Assets. Unity still takes time to load the Assets for registered Prefabs and Scene game objects. When a player moves within the world, the set of network-visible game objects changes. The player’s client is told about these changes as they happen. The `ObjectHide` message is sent to clients when a game object becomes no longer network-visible. By default, Mirror destroys the game object when it receives this message. When a game object becomes visible, the client receives an `ObjectSpawn` message, as if Mirror has spawned the game object for the first time. By default, the game object is instantiated like any other spawned game object. [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-visibility-on-the-host) Network Visibility on the Host ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The host shares the same Scene as the server, because it acts as both the server and the client to the player hosting the game. For this reason, it cannot destroy game objects that are not visible to the local player. Instead, there is the virtual method OnSetLocalVisibility in the NetworkVisibility class that is invoked. This method is invoked on all scripts that inherit from `NetworkVisibility` on game objects that change visibility state on the host. The default implementation of `OnSetLocalVisibility` disables or enables all renderer components on the game object. If you want to customize this implementation, you can override the method in your script, and provide a new behavior for how the host (and therefore the local client) should respond when a game object becomes network-visible or invisible (such as disabling HUD elements or renderers). [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#customizing-network-visibility) Customizing Network Visibility ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes you might want to use other kinds of visibility check, such as grid-based rules, line-of-sight tests, navigation path tests, or any other type of test that suits your game. To do this, you can create your own custom Network Observer from a [Script Template](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) via the Assets menu by clicking Create -> Mirror -> Network Observer. It may be helpful to understand how the Network Proximity Checker works. The Network Proximity Checker is implemented using the public visibility interface of Mirror. Using this same interface, you can implement any kind of visibility rules you desire. Each `NetworkIdentity` keeps track of the set of players that it is visible to. The players that a NetworkIdentity game object is visible to are called the “observers” of the NetworkIdentity. The Network Proximity Checker calls the `RebuildObservers` method on the Network Identity component at a fixed interval (set using the “Vis Update Interval” value in the inspector), so that the set of network-visible game objects for each player is updated as they move around. In the `NetworkVisibility` class (which your custom observer scripts inherit from), there are some virtual functions for determining visibility. These are: * **OnCheckObserver** This method is called on the server, on each networked game object when a new player enters the game. If it returns true, that player is added to the object’s observers. The Network Proximity Checker does a simple distance check in its implementation of this function, and uses `Physics.OverlapSphereNonAlloc` to find the players that are within the visibility distance for this object. * **OnRebuildObservers** This method is called on the server when `RebuildObservers` is invoked. This method expects the set of observers to be populated with the players that can see the object. The NetworkServer then handles sending `ObjectHide` and `ObjectSpawn` messages based on the differences between the old and new visibility sets. * **OnSetHostVisibility** This method is called on the server by the visibility system for objects on a host. Objects on a host (with a local client) cannot be disabled or destroyed when they are not visibile to the local client. So this function is called to allow custom code to hide these objects. A typical implementation will disable renderer components on the object. This is only called on local clients on a host. You can check whether any given networked game object is a player by checking if its `NetworkIdentity` has a valid connectionToClient. For example: [PreviousCustomchevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom) [NextGuideschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides) Last updated 4 years ago * [Network Proximity Checker Component](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-proximity-checker-component) * [Network Scene Checker Component](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-scene-checker-component) * [Network Visibility on Remote Clients](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-visibility-on-remote-clients) * [Network Visibility on the Host](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#network-visibility-on-the-host) * [Customizing Network Visibility](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management#customizing-network-visibility) Copy int hitCount = Physics.OverlapSphereNonAlloc(transform.position, visRange, hitsBuffer3D, castLayers); for (int i = 0; i < hitCount; i++) { Collider hit = hitsBuffer3D[i]; NetworkIdentity identity = hit.GetComponent(); if (identity != null && identity.connectionToClient != null) observers.Add(identity.connectionToClient); } --- # Basic | Mirror The Basic Example illustrates how to manage UI objects from the Player object using locally instantiated `PlayerUI` prefabs with [SyncVars](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars) and Events ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FEisctczKlZTsVAKaKz5q%252Fimage.png%3Falt%3Dmedia%26token%3D03771d14-0155-4b44-83d2-edf61dffc687&width=768&dpr=3&quality=100&sign=b02eb107&sv=2) The scene Canvas has a `CanvasUI` script with references to its children: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FB9TOxdEB7EvLv2MppZIf%252Fimage.png%3Falt%3Dmedia%26token%3D8f6a0acc-f1cc-4803-bb32-c1364f0cfdb1&width=768&dpr=3&quality=100&sign=d966aee2&sv=2) Scene Canvas The `PlayerUI` prefab is a UI fragment that has a `PlayerUI` script with references to its own children: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F8rczNg7Jr5ccOICoN5aP%252Fimage.png%3Falt%3Dmedia%26token%3Db672c056-1b3d-4fda-b48a-5beceb260ade&width=768&dpr=3&quality=100&sign=7bf24bf6&sv=2) PlayerUI Prefab The Player script on the Player object has a reference to the `PlayerUI` prefab and three `SyncVars`: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FpRIedJ2gjKa92TjReq2T%252Fimage.png%3Falt%3Dmedia%26token%3D9768456d-0cea-400a-8cf7-3a50fe7c29d2&width=768&dpr=3&quality=100&sign=ef645101&sv=2) Player Object The Player script also has three events that are invoked by the [SyncVar hooks](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvar-hooks) : When the Player object is spawned on the client, a `PlayerUI` is instantiated as a child of the `PlayersPanel` in the Canvas via the references provided in the `CanvasUI` script, and the `SetPlayer` method is called with the corresponding Player script reference. The `PlayerUI` script subscribes to the events above, and updates its UI elements as the `SyncVars` are updated from the server. [PreviousAdditive Sceneschevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/additive-scenes) [NextBilliardschevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/billiards) Last updated 2 years ago Copy public event System.Action OnPlayerNumberChanged; public event System.Action OnPlayerColorChanged; public event System.Action OnPlayerDataChanged; --- # Pong | Mirror A simple example for "How to built a multiplayer game with Mirror" is Pong, which is included in the AssetStore package of Mirror. It illustrates the usage of NetworkManager, NetworkManagerHUD, NetworkBehaviour, NetworkIdentity, NetworkTransform, NetworkStartPosition and NetworkingAttributes. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_nPOFGMK0lRNckh1x%252F-MH_nSaoETwyc6I8OSaC%252Fimage.png%3Falt%3Dmedia%26token%3D2cd49d20-0b60-4f56-8654-6c3df5b0f3a7&width=768&dpr=3&quality=100&sign=cbeabbf5&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/pong#setting-the-number-of-players) Setting the number of players ------------------------------------------------------------------------------------------------------------------------------------------ First of all, let's have a look at the NetworkManager object in the main scene. When adding the NetworkManager component to a gameobject, a few default settings are already set (**Don't destroy on Load**, **Run in Background**, ...) For playing Pong the maximum number of players is 2, so the setting **Network Info/Max connections** will also be 2. As there are no other scenes (room, online or offline scene) in this sample the properties for **Offline Scene** and **Online Scene** will stay empty. [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/pong#creating-the-player) Creating the player ---------------------------------------------------------------------------------------------------------------------- Furthermore every player needs a racket to play with. Each player who joins the game will have his own controllable object, which represents him within the game. This gameobject is called _PlayerObject_. For spawning the _PlayerObject_ a prefab has to be created, containing at least a NetworkIdentity component with **Local Player Authority** checked. The **Local Player Authority** allows the player to control and modify the gameobjects properties (e.g. for movement). The NetworkManager needs a reference to this prefab, which is located in **Spawn Info/Player Prefab**. To have the player movement synchronized over the network, the player prefab also contains a NetworkTransform. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_nPOFGMK0lRNckh1x%252F-MH_nUGvdvnNf9lyeeA5%252Fimage.png%3Falt%3Dmedia%26token%3D83b4b7a8-c58e-4673-96bc-1ddc5167e220&width=768&dpr=3&quality=100&sign=f54da515&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/pong#player-start-position) Player start position -------------------------------------------------------------------------------------------------------------------------- The main scene contains 2 gameobjects with only a NetworkStartPosition component (gameobjects RacketSpawnLeft, RacketSpawnRight in the scene). These transforms will be automatically registered by the NetworkManager as spawning positions. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_nPOFGMK0lRNckh1x%252F-MH_nW5kmrxKXkp_tOW0%252Fimage.png%3Falt%3Dmedia%26token%3D122bc450-1c13-4e70-9d75-5f9e68b8899b&width=768&dpr=3&quality=100&sign=a1510137&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/pong#setting-up-the-network) Setting up the network ---------------------------------------------------------------------------------------------------------------------------- A very convenient component for establish/testing connections is the [Network Manager HUD](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud) . It provides basic functionality for start a game as Client, Server, or Host (Client and Server at the same time). It requires the Network Manager component. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FA75OYfuVQbNM2XjjvvlA%252Fimage.png%3Falt%3Dmedia%26token%3D9ae0de90-091f-4aea-8070-d34bf6823658&width=768&dpr=3&quality=100&sign=88bc13c0&sv=2) Network Manager HUD [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/pong#the-ball-of-pong) The ball of Pong ---------------------------------------------------------------------------------------------------------------- The ball is the main focus of Pong, as this is the object needed to score points. Its NetworkIdentity component has neither **Server Only** nor **Local Player Authority** checked, as it's moved by the server physics engine and can be influenced by the players. As with the _PlayerObject_ the position is synchronized via NetworkTransform. When having multiple scenes, the ball can be spawned by the NetworkManager, but to keep this sample simple, it's placed directly within the main scene. [PreviousMultiple Additive Sceneschevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/multiple-additive-scenes) [NextRoomchevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/room) Last updated 3 years ago * [Setting the number of players](https://mirror-networking.gitbook.io/docs/manual/examples/pong#setting-the-number-of-players) * [Creating the player](https://mirror-networking.gitbook.io/docs/manual/examples/pong#creating-the-player) * [Player start position](https://mirror-networking.gitbook.io/docs/manual/examples/pong#player-start-position) * [Setting up the network](https://mirror-networking.gitbook.io/docs/manual/examples/pong#setting-up-the-network) * [The ball of Pong](https://mirror-networking.gitbook.io/docs/manual/examples/pong#the-ball-of-pong) --- # Network Room Player | Mirror The Network Room Player stores per-player state for the [Network Room Manager](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager) while in the room. When using this component, you need to write a script which allows players to indicate they are ready to begin playing, which sets the ReadyToBegin property. A game object with a Network Room Player component must also have a Network Identity component. When you create a Network Room Player component on a game object, Unity also creates a Network Identity component on that game object if it does not already have one. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNaRRnCFm7zCiVu-Vo%252F-MUNaVpAEA4qea-n3sYs%252Fimage.png%3Falt%3Dmedia%26token%3Da60e29b2-a999-4b5d-a470-a50e40685e8f&width=768&dpr=3&quality=100&sign=b491c84c&sv=2) * **Show Room GUI** Enable this to show the developer GUI for players in the room. This UI is only intended to be used for ease of development. This is enabled by default. * **Ready To Begin** Diagnostic indicator that a player is Ready. * **Index** Diagnostic index of the player, e.g. Player 1, Player 2, etc. * **Network Sync Interval** The rate at which information is sent from the Network Room Player to the server. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player#methods) Methods --------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player#client-virtual-syncvar-methods) Client Virtual SyncVar Hook Methods ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player#client-virtual-methods) Client Virtual Methods [PreviousNetwork Room Managerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager) [NextNetwork Start Positionchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-start-position) Last updated 2 years ago * [Methods](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player#methods) * [Client Virtual SyncVar Hook Methods](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player#client-virtual-syncvar-methods) * [Client Virtual Methods](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player#client-virtual-methods) Copy public virtual void IndexChanged(int oldIndex, int newIndex) { } public virtual void ReadyStateChanged(bool oldReadyState, bool newReadyState) { } Copy public virtual void OnClientEnterRoom() { } public virtual void OnClientExitRoom() { } [Obsolete("OnClientReady is deprecated, use the SyncVar ReadyStateChanged hook instead.")] public virtual void OnClientReady(bool readyState) {} --- # Network Manager HUD | Mirror The Network Manager HUD (“heads-up display”) is a quick-start tool to help you start building your multiplayer game straight away, without first having to build a user interface for game creation/connection/joining. It allows you to jump straight into your game play programming, and means you can build your own version of these controls later in your development schedule. It is not, however, intended to be included in finished games. The idea is that these controls are useful to get you started, but you should create your own UI later on, to allow your players to find and join games in a way that suits your game. For example, you might want to stylize the design of the screens, buttons and list of available games to match the overall style of your game. To start using the Network Manager HUD, either add the component to the same scene object that has the Network Manager component, or create an empty game object in your scene (menu: game object > Create Empty) and add the Network Manager HUD component to the new game object. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNZgpNW94GzZiRNOyN%252F-MUN_5jmgt9m3GmLl6q4%252Fimage.png%3Falt%3Dmedia%26token%3Daf5605b7-36ca-43ce-96d7-afe860fb2601&width=768&dpr=3&quality=100&sign=9bfde306&sv=2) * **Show GUI** Tick this checkbox to show the HUD GUI at run time. This allows you to reveal or hide it for quick debugging. * **Offset X** Set the horizontal **pixel** offset of the HUD GUI, measured from the left edge of the screen. * **Offset Y** Set the vertical pixel offset of the HUD GUI, measured from the top edge of the screen. The Network Manager HUD provides the basic functions so that people playing your game can start hosting a networked game, or find and join an existing networked game. Unity displays the Network Manager HUD as a collection of simple UI buttons in the Game view. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_7HNv0FFc1KzQEPc%252F-MUN_8N9V3Ta0JicF0so%252Fimage.png%3Falt%3Dmedia%26token%3D249a3510-bd23-4c7a-a3d0-29c1a291e5b0&width=768&dpr=3&quality=100&sign=26aa86b1&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#using-the-hud) Using the HUD --------------------------------------------------------------------------------------------------------------------------- The Network Manager HUD starts in Server + Client mode, and displays buttons relating to hosting and joining a multiplayer game. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#host-server--client) Host (Server + Client) Click the Host (Server + Client) button to start a game as a host on the local network. This client is both the host _and_ one of the players in the game. It uses the information from the Network Info section in the inspector to host the game. When you click this button, the HUD switches to a simple display of network details, and a Stop button which allows you to stop hosting the game and return to the main HUD menu. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_7HNv0FFc1KzQEPc%252F-MUN_Br01yskQXbFkxwD%252Fimage.png%3Falt%3Dmedia%26token%3D5e00f281-7aaf-40e0-89b9-b88f0104102d&width=768&dpr=3&quality=100&sign=555a676b&sv=2) When you have started a game as a host, other players of the game can then connect to the host to join the game. Click the Stop button to disconnect from the host. Clicking Stop also returns to the main HUD menu. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#client) Client To connect to a host on the internet use the text field to the right of the Client button to specify the address of the host. The default host address is “localhost”, which means the client looks on its own computer for the game host. In addition to _localhost_, you can specify an IPv4 address, and IPv6 address, or a fully-qualified domain name (FQDN), e.g. _game.example.com_, and the transport with resolve the name using DNS. Click Client to attempt to connect to the host address you have specified. Use the default “localhost” in this field if you are running multiple instances of your game on one computer, to test multiplayer interactivity. To do this, you can create a standalone build of your game, and then launch it multiple times on your computer. This is a common way to quickly test that your networked game interactions are functioning as you expect, without you needing to deploy your game to multiple computers or devices. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_7HNv0FFc1KzQEPc%252F-MUN_GRdcWxHHg9t4LS9%252Fimage.png%3Falt%3Dmedia%26token%3D765dce32-2074-44cd-a124-26b881b4ac86&width=768&dpr=3&quality=100&sign=7481f4dc&sv=2) When you want to test your game on multiple machines you need to put the address of the computer acting as host into the address text field. The computer acting as the host needs to tell their IP address to everyone running clients, so that you can type this into the box. For local clients on a LAN, that's the local IP address. For remote clients, that's the WAN IP address of the router of the host. Firewall rules and port-forwarding are generally required for a computer to act as host and accept connections from other computers, whether they're on the LAN or the internet. Enter the IP address (or leave it as “localhost” if you are testing it on your own machine), then click Client to attempt to connect to the host. When the client is attempting to connect, the HUD displays a Cancel Connection Attempt button. Click this if you want to stop trying to connect to the host. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_7HNv0FFc1KzQEPc%252F-MUN_JkTaiHIFin_DpMA%252Fimage.png%3Falt%3Dmedia%26token%3D06dcff57-a3f1-427f-a815-e9de33f1a0b5&width=768&dpr=3&quality=100&sign=3a219213&sv=2) If the connection is successful, the HUD displays the Stop button. Click this if you want to stop the game on the client and disconnect from the host: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_7HNv0FFc1KzQEPc%252F-MUN_LyucewFmu1Wd0YD%252Fimage.png%3Falt%3Dmedia%26token%3D96325b49-6afa-49d0-adbb-15101386fa78&width=768&dpr=3&quality=100&sign=b317983e&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#server-only) Server Only Click Server Only to start a game which acts as a server that other clients can connect to, but which does not act as a client to the game itself. This type of game is often called a “dedicated server”. A user cannot play the game on this particular instance of your game. All players must connect as clients, and nobody plays on the instance that is running as the server. A dedicated server results in better performance for all connected players, because the server doesn’t need to process a local player’s game play in addition to acting as server. You might also choose this option if you want to host a game that can be played over the internet (rather than just within a local network), but want to maintain control of the server yourself - for example, to prevent cheating by one of the clients, because only the server has authority over the game. To do this, you would need to run the game in Server Only mode on a computer with a public IP address. [PreviousNetwork Managerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-manager) [NextNetwork Ping Displaychevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-ping-display) Last updated 5 years ago * [Using the HUD](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#using-the-hud) * [Host (Server + Client)](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#host-server--client) * [Client](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#client) * [Server Only](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud#server-only) --- # Network Identity | Mirror circle-info See also [NetworkIdentityarrow-up-right](https://storage.googleapis.com/mirror-api-docs/html/d3/d88/class_mirror_1_1_network_identity.html) in the API Reference. The Network Identity component is at the heart of the Unity networking high-level API. It controls a game object’s unique identity on the network, and it uses that identity to make the networking system aware of the game object. It offers two different options for configuration and they are mutually exclusive, which means either one of the options or none can be checked. * **Server Only** Tick this checkbox to ensure that Unity only spawns the game object on the server, and not on clients. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNU-KWTh7YpgFrKDGp%252F-MUNUwxOwk-KqSrmH0_z%252Fimage.png%3Falt%3Dmedia%26token%3Dc3d823a9-f767-4389-9764-1a3f3148b35b&width=768&dpr=3&quality=100&sign=1cb373c2&sv=2) triangle-exclamation It is important to note that Mirror does not support Network Identities on nested GameObjects. Otherwise, Mirror will emit an error. To avoid this, ensure your parent GameObject is the only GameObject in the stack with a Network Identity. Child GameObjects can access the parents' Network Identity component via Unity's built-in GetComponentInParent scripting function. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-identity#instantiated-network-game-objects) Instantiated Network Game Objects ---------------------------------------------------------------------------------------------------------------------------------------------------------------- With the Mirror’s server-authoritative networking system, the server must spawn networked game objects with network identities, using `NetworkServer.Spawn`. This automatically creates them on clients that are connected to the server, and assigns them a `netId`. You must put a Network Identity component on any Prefabs that spawn at runtime for the network system to use them. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-identity#scene-based-network-game-objects) Scene-based Network Game Objects -------------------------------------------------------------------------------------------------------------------------------------------------------------- You can also network game objects that are saved as part of your Scene (for example, environmental props). Networking game objects makes them behave slightly differently, because you need to have them spawn across the network. When building your game, Unity disables all Scene-based game objects with Network Identity components. When a client connects to the server, the server sends spawn messages to tell the client which Scene game objects to enable and what their most up-to-date state information is. This ensures the client’s game does not contain game objects at incorrect locations when they start playing, or that Unity does not spawn and immediately destroy game objects on connection (for example, if an event removed the game object before that client connected). See [Networked Scene Game Objects](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/scene-gameobjects) for more information. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-identity#preview-pane-information) Preview Pane Information ---------------------------------------------------------------------------------------------------------------------------------------------- This component contains network tracking information, and displays that information in the preview pane. For example, the scene ID, network ID and asset ID the object has been assigned. This allows you to inspect the information which can be useful for investigation and debugging. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNU-KWTh7YpgFrKDGp%252F-MUNV2GUR2fQWhEPweWV%252Fimage.png%3Falt%3Dmedia%26token%3D9b692cc3-20c2-4131-8a1f-43917525d421&width=768&dpr=3&quality=100&sign=7967c8ab&sv=2) At runtime there is more information to display here (a disabled NetworkBehaviour is displayed non-bold): ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNU-KWTh7YpgFrKDGp%252F-MUNV3O6XFQIiUHK7f_r%252Fimage.png%3Falt%3Dmedia%26token%3De2cd8f8d-75b0-48c1-8cf5-1bce62df5e81&width=768&dpr=3&quality=100&sign=1e38b24c&sv=2) [PreviousNetwork Discoverychevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-discovery) [NextNetwork Managerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-manager) Last updated 2 years ago * [Instantiated Network Game Objects](https://mirror-networking.gitbook.io/docs/manual/components/network-identity#instantiated-network-game-objects) * [Scene-based Network Game Objects](https://mirror-networking.gitbook.io/docs/manual/components/network-identity#scene-based-network-game-objects) * [Preview Pane Information](https://mirror-networking.gitbook.io/docs/manual/components/network-identity#preview-pane-information) --- # Edgegap’s Dedicated Game Server Hosting – Plugin Guide | Mirror Edgegap helps you build and launch a dedicated game server in the cloud directly from Unity’s editor, without almost any coding or Linux/Cloud usage whatsoever. Which helps make game server hosting easy! _Thanks to Edgegap’s dedicated game server hosting plugin for Unity, Mirror users get 1.5 vCPU of cloud hosting for free with Edgegap’s free trial!_ [hashtag](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#overview) Overview ---------------------------------------------------------------------------------------------------------------- Integration of Edgegap is simple and takes a few minutes with 3 basics steps: 1. Installing Unity dependencies & Docker 2. Installing the Unity plugin & creating a free account on [Edgegaparrow-up-right](https://app.edgegap.com/) 3. Configuring, building & pushing the server to Edgegap Edgegap’s plugin walks you, step-by-step, making it the easiest way to add dedicated game server in Unity. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FSspy4lAuzYxgH1MDO0DJ%252F00%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520Overview%2520copy.png%3Falt%3Dmedia%26token%3De4024d65-b7db-47eb-a571-9c63ca4f35a8&width=768&dpr=3&quality=100&sign=fb6dd7f2&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#setting-up-your-project) Setting Up your Project ---------------------------------------------------------------------------------------------------------------------------------------------- circle-exclamation If you are installing a new project, rather than installing the latest version, we strongly recommend using the “LTS” (Long Term Service) version of Unity for your project, i.e., Unity 6.0 (6000.0.60f1) as of writing. This ensures compatibility with tools & services, and long-term support of Unity’s version for your projects. **1\. Installing Linux Build Support** From your **Unity Hub**, select **Installs**, select the **Manage** icon next to the Unity version you intend to use in your project and click **Add Modules**: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FOcg5CJr5gYHWrCfKVBmS%252F01%2520-%2520Mirror%2520Documentation%2520-%2520Install%2520Linux%2520Build%2520Support%2520-%2520Unity%2520Hub.png%3Falt%3Dmedia%26token%3Dfae0efd1-347d-41c7-8fea-e3c053940b2f&width=768&dpr=3&quality=100&sign=fa71b250&sv=2) Make sure to install all three of Unity’s Linux Build Support Modules. Namely: * Linux Build Support (IL2CPP), Linux Build Support (Mono), Linux Dedicated Server Build Support, Additionally, depending on your target platform OS, you will need to add: * **Windows**: Windows Build Support (Mono) * **Mac**: Mac Dedicated Build Support (IL2CPP) and Mac Dedicated Server Build Support * **WebGL**: Web Build Support ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F7rIuxFt4GiA7e2W5cFb3%252F03%2520-%2520Mirror%2520Documentation%2520-%2520Install%2520Linux%2520Build%2520Support%2520-%2520Modules.png%3Falt%3Dmedia%26token%3D84d91d1e-62ec-4dbb-a628-1ee24265e2ee&width=768&dpr=3&quality=100&sign=399e2c26&sv=2) circle-info For users with new projects, which modules to add will be prompted when selecting which version to install. Make sure to add it there. However, you can return at any time to add them as shown above. **2\. Installing Docker** Edgegap uses containers, which is a virtualization that ensures to can run on any hardware, anywhere in the world. Any containerization tool should work, but the easiest is to use Docker Desktop: [https://www.docker.com/products/docker-desktop/arrow-up-right](https://www.docker.com/products/docker-desktop/) Simply download it, install it, restart the dev machine, then open it (if it doesn’t open automatically at boot time. Then run it in the background. [hashtag](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#installing-the-unity-plugin) Installing the Unity plugin ------------------------------------------------------------------------------------------------------------------------------------------------------ From the top navigation menu in Unity, select **Window**, then **Package Manager**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FLTJ5R8KQU3JttmXOkY5U%252F04%2520-%2520Mirror%2520Documentation%2520-%2520Install%2520Plugin%2520-%2520Window.png%3Falt%3Dmedia%26token%3D4a426c18-78c3-4290-9abd-483201f9e919&width=768&dpr=3&quality=100&sign=9f4154c5&sv=2) Within the Package Manager, click on the "+" icon, then select **Add Project from Git**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fy1opZlc8gC9oMSDZDt84%252F05%2520-%2520Mirror%2520Documentation%2520-%2520Install%2520Plugin%2520-%2520Install%2520Package%2520from%2520git%2520URL.png%3Falt%3Dmedia%26token%3D2d87e51d-5ffb-4eb1-97a3-732411251bc8&width=768&dpr=3&quality=100&sign=a35f3325&sv=2) Paste Edgegap's Unity plugin URL: <[https://github.com/edgegap/edgegap-unity-plugin.git#partner/mirror-sourcearrow-up-right](https://github.com/edgegap/edgegap-unity-plugin.git#partner/mirror-source) \> ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fmk42K5RIde4tWsPNI9CV%252F06%2520-%2520Mirror%2520Documentation%2520-%2520Install%2520Plugin%2520-%2520Git%2520URL.png%3Falt%3Dmedia%26token%3Dc9746ad9-a3d4-4ce7-9671-48169ab39d00&width=768&dpr=3&quality=100&sign=e8bca3cd&sv=2) Select **Install**. That’s it! From the top navigation bar, select **Tools** and then open the plugin by clicking on **Edgegap Server Hosting**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FxreVHDakbTvC8ptjZk1U%252F07%2520-%2520Mirror%2520Documentation%2520-%2520Open%2520the%2520Plugin.png%3Falt%3Dmedia%26token%3D26561d38-c02f-4856-be1e-e3072186a7b9&width=768&dpr=3&quality=100&sign=8448b5d1&sv=2) The plugin automatically opens up. Select **Sign in with Edgegap** to start the process of creating an account (or sign-in to sync with the platform, for users with active accounts). ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FrAel4y0zUr8Iu8S4BBwr%252F08%2520-%2520Mirror%2520Documentation%2520-%2520Sign%2520in%2520with%2520Edgegap.png%3Falt%3Dmedia%26token%3D5e414c01-5f5c-4844-8e1a-3585513bcbb8&width=768&dpr=3&quality=100&sign=ea9796a2&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#create-a-free-account-on-edgegap) Create a Free Account on Edgegap ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Signing up to Edgegap is easy and free. Use your own **Google** or **GitHub** account, or sign-up with an **email**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FvJdw5KPGRUH2CKPGzMcX%252F09%2520-%2520Mirror%2520Documentation%2520-%2520Sign%2520in%2520Screen.png%3Falt%3Dmedia%26token%3D665b158d-25ed-47f9-8965-4e5379104349&width=768&dpr=3&quality=100&sign=c966681a&sv=2) You are now asked to name **Your Organization**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FRB9VXlL38Mi12Dyh0PmU%252F10%2520-%2520Mirror%2520Documentation%2520-%2520Your%2520Organization%2520Screen.png%3Falt%3Dmedia%26token%3D47331d84-ce15-4029-ad91-f678742a70a3&width=768&dpr=3&quality=100&sign=74b33ac3&sv=2) Automatically, the **OneClick Token Create Successfully** screen appears. This is your token (blurred here). Simply copy it by clicking on the clipboard icon. circle-exclamation Do not share your token with anyone or on public channels like Discord, as they could deploy game servers on your behalf! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fxt9FbryAJjXLeeXvLTfs%252F11%2520-%2520Mirror%2520Documentation%2520-%2520OneClick%2520Token.png%3Falt%3Dmedia%26token%3D595c099f-d980-47da-9522-147dc999c658&width=768&dpr=3&quality=100&sign=452dca5d&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#configuring-building-and-pushing-the-server-to-edgegap) Configuring, building & pushing the server to Edgegap ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- **1\. Validate your Token** Return to Unity and paste the token in the field under **1\. Connect your Edgegap Account**. Then, select **Validate Token**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F24XX3vcT0kOTRJo1xXJo%252F12%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Validate%2520Token.png%3Falt%3Dmedia%26token%3D446681eb-4736-4404-8b9b-e53912fc1b71&width=768&dpr=3&quality=100&sign=8e905b58&sv=2) **2\. Building your Game Server** After verifying successfully, you optionally can make sure that you have the Linux Server dependencies by clicking on **Install**. Then, select **Edit Settings** to make sure the game scenes you want to include are included. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FpaTfdLvoolSKif5pXCr4%252F04%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Build%2520your%2520Game%2520Server.png%3Falt%3Dmedia%26token%3Dcf10f50a-fcac-4c3c-ad66-505002224f48&width=768&dpr=3&quality=100&sign=b9c76480&sv=2) Under **Linux Server**, make sure the scenes are listed. If not, select **Open Scene List** and add them manually. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FhRYkb9bCsIX78hD2qcCX%252F14.A%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Build%2520Profile.png%3Falt%3Dmedia%26token%3Dbb44c92f-542c-452a-b19f-b2a35cf9f5fa&width=768&dpr=3&quality=100&sign=e5843cad&sv=2) Additionally, doublecheck that your build set up. Specifically, select **Network Manager** from your project’s hierarchy, and the under **Network Manager**, ensure 1. Under **Configuration**, that **Don’t Destroy on Load** is selected (i.e., the ✔) 2. **Headless Start Mode** is set to **Auto Start Server** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FxBc9CpaW3JsPHjQ3h5HJ%252F14.B%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Network%2520Manager%2520-%2520Copy.png%3Falt%3Dmedia%26token%3D7dd85372-e936-4ccb-bb48-9f939143b1dd&width=768&dpr=3&quality=100&sign=4ea09753&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FXGVrXFRgewuMWcd8ILMy%252F14.C%2520-%2520Mirror%2520Documentation%2520-%2520Auto%2520Start%2520Server.png%3Falt%3Dmedia%26token%3Db198918e-4c50-4f70-825e-c74eb5f6377d&width=768&dpr=3&quality=100&sign=e81a9bb6&sv=2) Return to the plugin and select **Build Server** to start the build process. You should see “Build succeeded” in green when complete. **3\. Containerize your Game Server** First, make sure Docker is running by selecting **Validate**. You should see “Docker is running” in green. While you may want to change the image name, build path, and tags in the future, we recommend skipping this entirely and select **Containerize with Docker** button to start the containerization process. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252Fhr71oOjBzOjmQZiPODHL%252F15%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Containerize.png%3Falt%3Dmedia%26token%3D48518ea1-0925-4b99-a476-2c3a8333c8b1&width=768&dpr=3&quality=100&sign=38484347&sv=2) After a short wait, you should see “Containerization succeeded” in green. **4\. (Optional) Test your Server Locally** Optionally, you can test your container locally by selecting **Deploy Local Container**. You may configure the server image tag, and Docker run parameters, but we recommend skipping this initially. If it succeeds, you should see “Container deployed successfully” in green. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FRFrOxTNJ75qWbSmJk6uH%252F16%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Test%2520Locally.png%3Falt%3Dmedia%26token%3D993c2ec2-807a-4380-a829-70d2b6213168&width=768&dpr=3&quality=100&sign=3b1ef93e&sv=2) The container should be visible within the “Container” tab in Docker Desktop. **5\. Upload to Edgegap** Now we’ll upload the game server to Edgegap’s registry so they can deploy it to their cloud network. Application name, server image name and server image tag are all pre-filled. While all can be edited, we suggest to keep things as-is for now. Select **Upload Image and Create App Version** button, which automatically uploads the build to Edgegap’s platform. circle-info Older images on your dev machine can be uploaded. Find the docker image name and tag in Docker Desktop under images tab. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FI5zsgw6vmbHjSDr0IwcW%252F17%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Upload%2520to%2520Edgegap.png%3Falt%3Dmedia%26token%3D8394130d-54b2-400c-b9b4-1f0674667d7c&width=768&dpr=3&quality=100&sign=a44d4d20&sv=2) After a bit of loading, a new web browser will open. This is your application’s **Version** parameters. You can customize the version’s name, resources parameters, and more. For now, click on **Submit** to create your version. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252F4juTZv3oMoEkFc9IteCm%252F18%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520App%2520Version.png%3Falt%3Dmedia%26token%3D7c29a257-3fff-4320-b9bd-3559ea6b8c14&width=768&dpr=3&quality=100&sign=30d8175&sv=2) circle-info Resources optimization is key to limit overall cloud usage. Edgegap offers vCPU fractioning, which means you can reduce your game server down to ¼ of a vCPU. When ready, make sure to check out Edgegap’s [analyticsarrow-up-right](https://app.edgegap.com/analytics/dashboards/list) and recommended [server builds optimizationarrow-up-right](https://docs.edgegap.com/learn/unity-games/getting-started-with-servers#optimize-server-builds) strategy Then, the **Create Port** screen appears. Here you can change the **port**, and the **protocol type**. If you use KCPTransport the default port of 7777 and UDP. circle-info If you are working on a WebGL project, then use 7778 and WS protocol. For other transports, select the corresponding protocol an port configured in Network Manager in your server build. Select **Submit** to create your deployment. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FRJb35F89EMFqPCUK4JfK%252F19%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Create%2520Port.png%3Falt%3Dmedia%26token%3D28e23aba-af46-40cd-92ec-6b217cf93ab0&width=768&dpr=3&quality=100&sign=b59fb02d&sv=2) **6\. Deploy to Cloud** The final step is to select which version to deploy to Edgegap’s cloud network. Here, your latest application will be preset but can be changed. You must manually select **Application Version** by simply clicking on the drop down (the ▼ on the right) and the latest versions will be shown, here in the image highlighted in green: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FNWucXBvD5n3bCDBN8qwA%252F20%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Deploy%2520to%2520Cloud.png%3Falt%3Dmedia%26token%3D741beac7-8789-4264-9537-0e4fc2429054&width=768&dpr=3&quality=100&sign=8454d352&sv=2) Once selected, simply select **Deploy to Cloud**. This automatically opens your deployments’ page on the Edgegap’s platform. After a few seconds, the deployment will change from “deploying” to “ready”. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FS1rSvAG2h7g4SPNEpV4E%252F21%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Deployment%2520Dashboard.png%3Falt%3Dmedia%26token%3D49c71c29-4923-4f2a-a786-5b8fee02316d&width=768&dpr=3&quality=100&sign=3e7a8e63&sv=2) Once that’s done, click on the deployment. This opens up the **Deployment Details** page. Scroll down and make sure to note the **Host URL** alongside the **External Port**. Copy the Host URL using the clipboard. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FY9DBJ0Z3uaIQgNLMCucs%252F22%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Deployment%2520Host%2520URL%2520%2526%2520External%2520Port.png%3Falt%3Dmedia%26token%3Db4b6da02-1790-4489-a80b-183375347b4c&width=768&dpr=3&quality=100&sign=c5ff7367&sv=2) circle-info While internal ports for the server process are defined as part of app version, external ports are assigned at random once a deployment is created, so that a potential malicious party (hacker) is slowed down and detected before they can cause damage. Back in Unity, select the **Network Manager** from your project’s hierarchy. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FaHfNLXm0QjdmzEwYgJoC%252F23%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Network%2520Manager.png%3Falt%3Dmedia%26token%3D4bafe67d-6e8b-4145-a70c-642163a1bcdf&width=768&dpr=3&quality=100&sign=bb145a41&sv=2) Within the **Inspect Tab**, make sure to set: 1. Paste the **Host’s URL** from the deployment to the **Network Address** 2. Replace the default **Port** (usually 7777) to the **External Port** from the deployment ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FWlER1CsHLumaIEOCBMVY%252F24%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Network%2520Manager%2520Inspector.png%3Falt%3Dmedia%26token%3De5fbc617-0465-4d5c-96fd-7c9f097e3d45&width=768&dpr=3&quality=100&sign=ee40b785&sv=2) Then launch the scene in Unity Editor, and test the project: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FB2P6KcFe7oqtzOPHQLug%252F25%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Test%2520Scene.png%3Falt%3Dmedia%26token%3Dbf8757d1-b645-4fff-af3a-81e5e139a56c&width=768&dpr=3&quality=100&sign=11d262fc&sv=2) circle-check It's important to understand the magic that is happening here. Not only can you launch a game server with Two Clicks now. You can even launch thousands of servers with another click on Edgegap's website! 🤩 To reduce costs (if you are paying), you can press **Stop Last Deployment** in the plugin once you are done. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FR9JPPCTcSc1QZAItFMjb%252F26%2520-%2520Mirror%2520Documentation%2520-%2520Plugin%2520-%2520Stop%2520Last%2520Deployment.png%3Falt%3Dmedia%26token%3D8355c307-faa2-4f7e-aabe-5db62314f2a4&width=768&dpr=3&quality=100&sign=b3c0f448&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#troubleshooting-connection-issues) Troubleshooting Connection Issues ------------------------------------------------------------------------------------------------------------------------------------------------------------------ If your Server Status says **Ready** but you can't seem to connect, try this: * On the Edgegap website, go to Deployments -> select your Deployment -> select **Container Logs**, check the log files to see if your game server launched or if there are issues. * If it says "exec user process caused: no such file or directory": this can happen if you pushed an ARM build to Edgegap's x86 infrastructure. We already updated the plugin to properly cross compile from ARM so this generally should not happen anymore. * If everything seems fine but you still can't connect, please talk to an Edgegap employee in the Mirror Discord's **#edgegap** channel. [PreviousHosting with a Remote Desktopchevron-left](https://mirror-networking.gitbook.io/docs/hosting/hosting-with-a-remote-desktop) [NextSecurity Overviewchevron-right](https://mirror-networking.gitbook.io/docs/security/security-overview) Last updated 5 months ago * [Overview](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#overview) * [Setting Up your Project](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#setting-up-your-project) * [Installing the Unity plugin](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#installing-the-unity-plugin) * [Create a Free Account on Edgegap](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#create-a-free-account-on-edgegap) * [Configuring, building & pushing the server to Edgegap](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#configuring-building-and-pushing-the-server-to-edgegap) * [Troubleshooting Connection Issues](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#troubleshooting-connection-issues) --- # Cheats & Anticheats | Mirror ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#introduction) Introduction Back in 2009-2015 Before working on Mirror & uMMORPG, I tried to learn about MMOs by reverse engineering them and selling Bots to make a living. I will share some of the lessons learned based on questions in our Discord. This article is **incomplete**, intended to give a brief introduction into the most frequently asked topics in our discord. If you want to know more, let me know. At first we will understand Server Authority & Client Authority, which is the first major attack vector. We will also talk about authority-independent attacks and how to protect against them. circle-info As rule of thumb, never trust the client! ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#server-authority-vs.-client-authority) Server Authority vs. Client Authority First things first. Mirror is server authoritative by default. In other words, the server makes the all decisions. Cheaters usually modify the client to exploit games where the client is trusted with some decisions (aka client authority). In other words, as long as you use full server authority you are fine until someone physically hacks your server machine. If you use client authority for parts of your game (like movement), then those are the parts you need to worry about. Just to be clear, here is the difference between server & client authority explained by using a health potion Server Authority Client Authority Client: may I use this potion? Client: I use this potion. My new health is 100! Server: verifying... Server: ¯\\\_(ツ)\_/¯ Server: your new health is 100! In practice, you need to validate any client input in `[Commands]`. Here is an [actual videoarrow-up-right](https://www.youtube.com/watch?v=C0txZCB9ZXc) of someone exploiting a game made with Mirror where the devs didn't verify client input. The game _probably_ has a `CmdSellItem` function like this: Copy [Command] void CmdSellItem(int slot, int amount) { // get player's item at inventory slot Item item = player.inventory[slot]; // sell to npc item.amount -= amount; player.gold += item.price * amount; } Notice how we blindly trust the client to send the correct amount. There is no check whatsoever. If the player only has one item, but an attacker sends 'amount = 100', we would still trust it and sell 100 items. Instead, we need to **validate any input**: ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#client-authority-the-root-of-all-evil) Client Authority - the root of all Evil #### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#trusting-the-client-for-movement) Trusting the Client for Movement If Mirror is fully server authoritative by default and client authority allows for cheating, then why would anyone use client authority? Because it's easy. A lot of games use client authority for movement at first, or forever. In server authority, the client would have to ask the server before every move. This introduces a lot of latency between pressing the key and seeing the actual movement. It's not fun at all. In client authority mode, the player moves as soon as the key is pressed. **Instead of asking** the server to move, it tells the server that it moved. This feels great, but also introduces cheaters to **tell the server** whatever they like, e.g. "I moved here twice as fast". Networked movement is difficult. It's possible to have fast movement that is also server authoritative (rubberbanding / prediction / etc.), but many opt not to do it at first in order to save months of development time. #### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#trusting-the-client-for-input) Trusting the Client for Input In some genres like First Person Shooters, trusting the client with some parts of the game is inevitable. In this case, aiming. Whenever we trust the client, that trust can be exploited by hackers. In FPS games, an **Aim Bot** can pretend to move the cursor onto another player more quickly. And since the server trusts the client with moving the cursor, it opens up for cheating with no easy solution. circle-info To summarize, we may _want or need to_ trust the client with some parts of our game. Those are the parts we need to protect against cheating. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#server-authority-cheats) Server Authority "Cheats" Just to be clear, even for 100% server authoritative games like MMOs, there are still attack vectors. The point of this article is to worry about the most **obvious** attacks on client authority first. Even if the server does not trust the client, there is still room for Bots which technically don't cheat, except for automating tasks that the player is supposed to do manually. **Bots** are tools that analyze the game state and generate input to **automatically** farm gold or kill monsters while the player isn't around. This can go to extremes where some players use hundreds of Bots to farm and then sell in-game gold for real money. circle-info Keep in mind that server authoritative cheats are a **luxury problem**. If your MMO becomes so successful that people develop Bots, then you pretty much made it. Protecting against server authoritative "cheats" goes beyond the scope of inital development. There will be plenty of time to deal with those after releasing. Someone running a Bot in his basement is not a serious threat until your game, unless it gets out of hand. And just to be clear, it's possible to **detect Bots** both on the client side and on the server side. But worry about it 5 years from now when the problem arises, not today. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#how-cheats-are-made) How Cheats are Made Let's do a quick dive into how cheats are actually made. Your game stores a whole lot of relevant information in its memory. For example: the local player's location, other player's locations, monster locations, health, names, etc. #### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#finding-memory-locations) Finding Memory Locations The majority of cheats need to read some of that information out of your game's memory. Tools like **Cheat Engine** allow you to search the game's memory for specific values. For example, if you have 100 health then you search for "100" and may find 10,000 places in memory with the value "100". But if you take a potion and increase your health to 200, then you can likely narrow it down to a handful of values that previous were "100" and now changed to "200". If you do this a couple of times, then you can usually narrow it down to one place in memory. For example, the local player's health might be stored at the memory address `0xAABBCCDD`. But there is one **problem**: next time we start the game, the game will set up the world again and your player's health is most certainly not at the same memory address anymore. Tools like Cheat Engine allow you to **"find what accesses..."** that memory location by setting breakpoints. Use a potion again, the breakpoint fires and now you know which part of your game accesses that memory location. Instead of just `Health`, you now have `Player->Health` (this is a simplification, in practice you go from `0xAABBCCDD` to a pointer with an offset like `[0x00FF00FF+0x8]` where 0x00FF00FF is the location of your player object in memory, and `0x8` is the offset for `Player->Health`. It's likely that `Player->Mana` would be at `+0x12`, or at the next place in memory. This process can be repeated until you have `Game->Player->Health`where `Game` is finally an address relative to the program's entry point. In other words, we can now always read the Player's health even after restarting the game. This process can be repeated for inventory, skills, monsters, positions, etc. The more information we can find, the easier it is to write cheats. If our game uses **client authority** then we can actually modify the Player's Health in memory! If we use server authority, then we can still modify it in memory but the change is only visible on this client. The server doesn't trust the client with health, and the next time it syncs the new health to the client, the value in memory will be overwritten again. circle-check This is how Mirror's **\[SyncVar\]** works! You can modify them in Cheat Engine, but nobody cares because they are server authoritative. #### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#making-it-harder-to-find-memory-locations) Making it harder to find Memory Locations The process of finding memory locations via pointers & offsets is cumbersome. Whenever the game changes, the offsets change too. For example, if previously we had And the game is changed to: Then the cheat developer would have to manually search for all offsets in memory again. This is somewhat painful to deal with. circle-check Messing with the memory layout occasionally is a nice way to make reverse engineering more difficult. Protecting against reverse engineering is a function of **return vs. effort**. Nobody will spend 10 hours a day reverse engineering if the hack only ends up making $10/month. The harder we make it, the less it'll be worth it. #### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#projecting-memory-values) Projecting Memory Values Here is a fun little technique that can actually be done in any game, without much risk. Instead of storing Health directly, we could store a projected value like: This is a simplified example, but the idea is to not store our "100" health directly in memory. Instead we store the value modified by one, or by more complex projections. This already makes the whole **Cheat Engine** initial finding process really depressing while adding virtually no risk. Nothing can really go wrong if you do this in Unity. circle-check Projecting Memory values is an easy way to make cheat development more annoying. Note that there is a minor performance impact and note that this is only useful if you use IL2CPP in Unity. circle-info When protecting against cheats, there is a **fine balance** between making cheater's life harder while not annoying honest players. Some techniques like UPX packing (see below) have a high probability of annoying everyone. Other techniques like Projecting Memory have a low probability of annoying anyone. #### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#making-it-harder-to-access-memory) Making it harder to access Memory There are various techniques to make reverse engineering more painful to begin with. For example: * **Fake entry points** that change dynamically, e.g. with exe packing like **UPX packer**. Those aren't too hard to unpack, but it adds difficulty. * _Note that UPX packed executables are often flagged as viruses._ * **Detecting Debuggers** like Cheat Engine/MHS via **IsDebuggerPresent**. Note that this is pretty easy to work around because everyone knows IsDebuggerPresent arleady. More advanced techniques might involve tricks like measuring time between instructions. For example, if we measure a simple integer multiplication with a **StopWatch at runtime** and it ends up taking several milliseconds, then someone is most likely stepping through this code with a debugger. * **Virtualization** with tools like **Themida** or **Enigma Packer** is the holy grail when it comes to protecting against reverse engineering. If finding memory locations in regular processes is hard, then finding them in processes inside of virtual machines is orders of magnitude harder. Back when we used to reverse engineer games, we would never touch virtualized processes simply because the effort vs. reward would not ever be worth it. Nobody is going to spend half a year analyzing your virtual machine instructions, unless your game is as huge as World of Warcraft. * _Note that virtualized executables are often flagged as viruses. You would need a custom virtualization engine that is not flagged as a virus._ circle-info **Note** that many of those techniques can be risky in **Unity,** which already introduces several layers of complexity by going from **C#**\->**IL**(->**IL2CPP**\->**Assembly**). The probability of messed up entry points breaking something somewhere is high. As rule of thumb, use **IL2CPP** in any case, since it changes the game from IL to Assembly, which is way harder to reverse engineer already. If cheating becomes a serious problem, consider Virtualization. Now that we understand how cheats are developed, we can take a look at how some common cheats work and how to protect against them. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#ollydbg-ida-code-caves) Ollydbg/IDA/Code Caves Let's say your game has a function like: Which might produce _(simplified)_ assembly code like: Hackers can use advanced debugging tools to modify your game's assembly to: Instead of searching and modifying memory values with Cheat Engine, it's possible to **modify the game's own assembly** code directly. Modifying the game's assembly can be extremely powerful for developing hacks. **Code Caves** are often used to inject custom functions into the game, for example: In C#, this would be equivalent to the user injecting his own code into our Health function like: This is a simplified example, but a very common technique to know about. To protect against custom assembly, it might be smart to generate checksums of your exe files. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#wall-hacks-esp) Wall Hacks / ESP In first person shooters, wall hacks are one of the most common cheats. People can modify your executable to show players behind walls. This is reasonably easy to do and pretty common. To protect against it: * Make reverse engineering as difficult as possible (see above chapter) * Use Mirror's **Interest Management** to not display far away players. You could implement raycast based Interest Management where players are only sent to clients if they are actually seen. * _Note that you would want some kind of tolerance to send them early enough, e.g. send 1s before they are seen. This is not perfect, but it's better than allowing players to see all other players all the time. Interest Management is huge for this._ * Detect Wall Hacks at runtime and ban cheaters using them. This is a hard problem, even popular games like Counter-Strike have a really hard time dealing with this. It's a constant battle. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#speed-hacks) **Speed Hacks** If you made the choice to use client authoritative movement becuase it's easier, then you will most likely encounter speed hacks in your game eventually. Speed hacks can be implemented in various ways, ranging from simply modifying `Player.Speed` in memory, to messing with the computer's clock speed which is pretty hard to work around from Unity. To protect against it: * Check the movement speed on the server. Allow for some tolerance for network conditions. Many games allow 10-15% tolerance, but anything higher than that is most likely a speed hack. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#bots) Bots As mentioned before, Bots are particularly evil since they don't requires any _real_ cheats or client authority. Additionally, they can mess up your game's economy and make it simply not fun to player if everyone around you is a Bot. To protect against it: * Make finding memory locations hard. See chapters above. * Adjust your memory layout occasionally. Add unnecessary values between `Player.Health` and `Player.Mana` sometimes. * Adjust your network protocol occasionally. The most advanced Bots don't even need to read your memory. They use work with your game's send/recv functions directly. Modify your NetworkMessage opcodes and layout occasionally and you will make reverse engineering really painful. * Detect known Bot.exe processes by checksum, name, etc. * _Note that this too often flags your game as a virus. Games shouldn't look for running processes._ * Detect Bot **Patterns** on the server. This is how I would do it if Bots become a serious problem. * In the simplest form, if someone is playing 24/7 for a week on end then it's probably a Bot, or in rare cases some guy in an internet cafe. * If the player always uses the same path or levels at the same spot all the time, it's probably a Bot. * Add a **Report button** in your game. Look into reported players. Try to talk to them and see if they respond, etc. * Spawn **Honeypot Monsters** in places of high activity. If a certain area has a whole lot of monster kills over a period of time, spawn a obviously different looking but extremely strong monster in that area. Regular players would notice and move elsewhere for a while. Bots would hit it and die. Again, those are simplified answers to a complex problem. If your game becomes successful, it will be a constant battle. Which is fine, as long as you know that you are even fighting a battle. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#silent-delayed-detection) Silent, Delayed Detection One of the biggest mistakes games make is to let the user know when a cheat or reverse engineering tool was detected. All it does is let the reverse engineer know where to look in the code in order to disable the checks. If we go through all the work of detecting cheats and debuggers, we should keep quiet and use the information to our advantage. Instead of loudly announcing a cheat attempt, quietly send some info to the server. Flag the player in a database. Do **not** immediately ban or kick anyone. It's smarter to wait a random amount of time. * Users might try multiple cheats with different versions over the month. * Reverse Engineers might use different tools and modify the game in different ways. If we only ban people once a month, then it's not obvious at all what caused the ban. It will introduce **huge turnaround** times to test which cheats get detected and which don't. circle-check Silent Detection is the most powerful tool we have to win the fight against cheaters. Use time and information to your advantage. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#free-to-play-vs.-paid-games) Free to Play vs. Paid Games Here is one final consideration which I'll most likely also do for my own game. While free 2 play games are great to attracts huge amounts of players, there might be value in paid games if you are just a small indie developer not ready to deal with hordes of fake accounts and hackers. People having to pay a one time price to play your multiplayer game introduces a huge hurdle where hackers and cheaters would have to buy your game again if they got banned. Additionally it adds some level of verification to make sure people can't just create accounts over and over again. You could ban credit cards etc. if needed. ### [hashtag](https://mirror-networking.gitbook.io/docs/security/cheating#summary) Summary To summarize, cheating is a complex topic and there will never be a final solution. Imho make everything you can server authoritative. For movement, at least aim to make it server authoritative at some point, e.g. after releasing your game when you start seeing the first speed hacks or when you actually have some breathing room. Once your game becomes successful, probably someone to fight the battle. There's plenty you can do to make it harder. Ultimately, it's function of effort vs. reward. The more annoying you make it to cheat, the more likely it is that people won't bother or will just move to easier targets. This topic could fill a whole book, but I hope you learned a few of the basics from this. [PreviousCheat Protection Stageschevron-left](https://mirror-networking.gitbook.io/docs/security/cheat-protection-stages) [NextCommunity Translationschevron-right](https://mirror-networking.gitbook.io/docs/community-guides/community-translations) Last updated 3 years ago * [Introduction](https://mirror-networking.gitbook.io/docs/security/cheating#introduction) * [Server Authority vs. Client Authority](https://mirror-networking.gitbook.io/docs/security/cheating#server-authority-vs.-client-authority) * [Client Authority - the root of all Evil](https://mirror-networking.gitbook.io/docs/security/cheating#client-authority-the-root-of-all-evil) * [Server Authority "Cheats"](https://mirror-networking.gitbook.io/docs/security/cheating#server-authority-cheats) * [How Cheats are Made](https://mirror-networking.gitbook.io/docs/security/cheating#how-cheats-are-made) * [Ollydbg/IDA/Code Caves](https://mirror-networking.gitbook.io/docs/security/cheating#ollydbg-ida-code-caves) * [Wall Hacks / ESP](https://mirror-networking.gitbook.io/docs/security/cheating#wall-hacks-esp) * [Speed Hacks](https://mirror-networking.gitbook.io/docs/security/cheating#speed-hacks) * [Bots](https://mirror-networking.gitbook.io/docs/security/cheating#bots) * [Silent, Delayed Detection](https://mirror-networking.gitbook.io/docs/security/cheating#silent-delayed-detection) * [Free to Play vs. Paid Games](https://mirror-networking.gitbook.io/docs/security/cheating#free-to-play-vs.-paid-games) * [Summary](https://mirror-networking.gitbook.io/docs/security/cheating#summary) Copy [Command] void CmdSellItem(int slot, int amount) { // valid slot? if (0 <= slot && slot <= player.inventory.Count) { // get player's item at inventory slot Item item = player.inventory[slot]; // valid amount? if (0 < amount && amount <= item.amount) { // sell to npc item.amount -= amount; player.gold += item.price * amount; } } } Copy class Player { int Level; // at +0 in memory int Health; // at +4 in memory int Mana; // at +8 in memory } Copy class Player { int Class; // at +0 in memory int Level; // NOW at +4 in memory int Health; // NOW at +8 in memory int Mana; // NOW at +12 in memory } Copy struct AntiCheatInt { int projected; public int Value { get => projected + 1; set => projected = value - 1; } } Copy void SetHealth(int health) { this.health = health; } Copy ... mov edi, eax // edi is this.health, eax is the new value ... Copy ... mov edi, 100 // always sets health to 100 ... Copy ... JMP 4 // jump to our custom code ... mov edi, eax // do the original thing ... custom code ... // do whatever we want JMP 2 // jump back to the original function ... Copy void SetHealth(int health) { CodeCave(health); } void CodeCave(int health) { this.health = health; // do all kinds of magic here // for example, if health==0 then call the code // that clicks on the Respawn button to respawn // automatically. } --- # Communications | Mirror When you are making a multiplayer game, In addition to synchronizing the properties of networked game objects, you are likely to need to send, receive, and react to other pieces of information - such as when the match starts, when a player joins or leaves the match, or other information specific to your type of game, for example a notification to all players that a flag has been captured in a “capture-the-flag” style game. Within the Mirror networking High-Level API there are three main ways to communicate this type of information. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications#remote-actions) Remote Actions -------------------------------------------------------------------------------------------------------------------- Remote actions allow you to call a method in your script across the network. You can make the server call methods on all clients or individual clients specifically. You can also make clients call methods on the server. Using remote actions, you can pass data as parameters to your methods in a very similar way to how you call methods in local (non-multiplayer) projects. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications#networking-callbacks) Networking Callbacks -------------------------------------------------------------------------------------------------------------------------------- Networking callbacks allow you to hook into built-in Mirror events which occur during the course of the game, such as when players join or leave, when game objects are created or destroyed, or when a new Scene is loaded. There are two types of networking callbacks that you can implement: * Network manager callbacks, for callbacks relating to the network manager itself (such as when clients connect or disconnect) * Network behaviour callbacks, for callbacks relating to individual networked game objects (such as when its Start function is called, or what this particular game object should do if a new player joins the game) [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications#network-messages) Network Messages ------------------------------------------------------------------------------------------------------------------------ Network messages are a “lower level” approach to sending messages (although they are still classed as part of the networking “High level API”). They allow you to send data directly between clients and the server using scripting. You can send basic types of data (int, string, etc) as well as most common Unity types (such as Vector3). Since you implement this yourself, these messages are not associated directly with any particular game objects or Unity events - it is up to you do decide their purpose and implement them! [PreviousSyncSortedSetchevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncsortedset) [NextRemote Actionschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) * [Remote Actions](https://mirror-networking.gitbook.io/docs/manual/guides/communications#remote-actions) * [Networking Callbacks](https://mirror-networking.gitbook.io/docs/manual/guides/communications#networking-callbacks) * [Network Messages](https://mirror-networking.gitbook.io/docs/manual/guides/communications#network-messages) --- # Custom | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#custom-interest-management) Custom Interest Management ------------------------------------------------------------------------------------------------------------------------------------------------- **Mirror** allows you to implement custom Interest Management solutions. For example: * **Raycast** based so DotA players don't see other players behind a wall or in the bushes * **Predictive Raycasting** for Counter-Strike like games. Wallhacks show players behind walls. You could create a custom interest management system to only send enemies to the player shortly before they would pop out behind a wall. In first person shooters, players move fast so you would still have to send them a couple of milliseconds before they become visible. All of the above custom solutions are possible in Mirror. To understand how interest management can be implemented, let's walk through it step by step. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#script-template) Script Template Mirror includes a [**Script Template**](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) for custom interest management. It is fully commented with all the virtual method overrides already stubbed out for you. If you used our legacy Interest Management system before, then these should look familiar. * **OnCheckObserver** is called when someone spawns. Returns true if 'identity' can be seen by 'newObserver' * **OnRebuildObservers** rebuilds observers for the given **Network Identity**. The result is stored in **newObservers**. * Mirror will automatically put **newObservers** into **identity.observers** internally. We don't do this directly because it's a bit more complicated than adding/removing. Mirror takes care of it. Nothing to worry about :) * **RebuildAll** is a helper function to rebuild every **spawned** Network Identity's observers. * Implementations probably want to call this every interval. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#distance-example) **Distance** Example Distance Interest Management is the easiest, straight forward implementation. Let's walk through it to see how to inherit from the abstract `InterestManagement` class. Copy public class DistanceInterestManagement : InterestManagement { [Tooltip("The maximum range that objects will be visible at.")] public int visRange = 10; [Tooltip("Rebuild all every 'rebuildInterval' seconds.")] public float rebuildInterval = 1; double lastRebuildTime; public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver) { return Vector3.Distance(identity.transform.position, newObserver.identity.transform.position) <= visRange; } public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers, bool initialize) { Vector3 position = identity.transform.position; // for each connection foreach (NetworkConnectionToClient conn in NetworkServer.connections.Values) // if authenticated and joined the world if (conn != null && conn.isAuthenticated && conn.identity != null) // check distance to our 'identity' if (Vector3.Distance(conn.identity.transform.position, position) < visRange) // add to result newObservers.Add(conn); } [ServerCallback] void Update() { // rebuild all spawned NetworkIdentity's observers every interval if (NetworkTime.time >= lastRebuildTime + rebuildInterval) { RebuildAll(); lastRebuildTime = NetworkTime.time; } } } This isn't too complicated, is it? * **OnCheckObserver** simply compares the distance between the newly spawned identity and a connection. A connection has a main player, which is what we use for the distance check here. * _Note that you could also check against every object that the connection owns. For example, if Bob spawns and Alice isn't close enough, Alice's pet might be close enough and so Alice and Bob should still see each other, despite being a bit out of normal range._ * **OnRebuildObservers**'s job is to return that HashSet of **Network Connection**s that can see our **Network Identity**. So obviously, we just iterate all **NetworkServer.connections** and check their main player's distances to our Network Identity. * _Note that we only check the ones that are authenticated and have a player in the world. Connections that are still logging in or choosing characters shouldn't observe anything._ * **Update**'s job is to actually call **RebuildAll()** every now and then. If we don't call **RebuildAll()**, then Mirror would never rebuild observers. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#host-mode-visibility) Host Mode Visibility In host mode, someone runs the server while also playing on it themselves, so you might think: * **I am the server**. The **server sees everyone**. Therefore, **I should see everyone**. This is _technically true_, but if you were fortunate enough to ever be on a **LAN** party then you'll remember it differently: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MWIH5b6Uj8Kpg9g9x0s%252F-MWIKSS8jvO-JucO27ZX%252Fimage.png%3Falt%3Dmedia%26token%3Dc550e3fb-df3f-4f79-9b2d-5f5b23f99be6&width=768&dpr=3&quality=100&sign=777e4126&sv=2) The best of days. For example, someone on a LAN hosts a Counter-Strike or DotA game. Let's think about that case for a moment: * The **host** runs the **server**. The **server** holds the **whole world** state in memory, yet the **host player** only sees the world around him. The idea is for the **host player** to be a regular player in the game. LAN parties wouldn't be much fun if you play DotA / Counter Strike and the host always sees everyone else's position, right? circle-info **Obviously, the host can cheat.** If you cheat on LAN then you need professional help. Mirror has a virtual method `SetHostVisibility(NetworkIdentity, bool)` that enables / disables renderers in host mode. In other words, the world state is still there - the host player just doesn't see it. You can override this in your custom system to suit your needs. [PreviousTeamchevron-left](https://mirror-networking.gitbook.io/docs/manual/interest-management/team) [NextLegacychevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management/legacy-interest-management) Last updated 4 months ago * [Custom Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#custom-interest-management) * [Script Template](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#script-template) * [Distance Example](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#distance-example) * [Host Mode Visibility](https://mirror-networking.gitbook.io/docs/manual/interest-management/custom#host-mode-visibility) --- # Examples | Mirror Mirror includes several small examples to help you learn how to use various features and how to set things up so they work together. Only a select few have documentation pages, check the Mirror/Examples directory in your Unity Project for more examples of how to use Mirror. * [Additive Levels](https://mirror-networking.gitbook.io/docs/manual/examples/additive-levels) The Additive Levels example demonstrates using Additive Scenes as levels with Scene Interest Management, custom scene loading with a fade transition, and teleporting the player from one scene to another via respawning. * [Additive Scenes](https://mirror-networking.gitbook.io/docs/manual/examples/additive-scenes) The Additive Scenes example demonstrates a server additively loading a sub-scene into a main scene at startup, and having a server-only trigger that generates a message to any client whose player enters the trigger zone to also load the sub-scene, and subsequently unload it when they leave the trigger zone. Only players inside the trigger zone can see the objects in the sub-scene. Network Proximity Checker components are key to making this scenario work. * [Basic](https://mirror-networking.gitbook.io/docs/manual/examples/basic) Basic is what it sounds like...the most rudimentary baseline of a networked game. Features SyncVars updating random UI data for each player. * Benchmark Allows for mass testing of Enemy NPC's (monsterous red cubes!). See the Spatial Hashing Interest Management component at work, joining clients will only receive data from nearby enemies. * Benchmark Idle Similar to above, mass test idle networked objects each with a colour sync var, settings can be changed via NetworkManager inspector. * Billiards Mouse drag the white ball to apply force, hits are send to server via \[Command\]. * Billiards Predicted Similar to above, but with prediction, this solves the possible delay that a Command->ClientRpc/NetworkTransform position result, would normally have. * CCU SoonTM * Character Selection Demonstrates how to use multiple prefabs for player spawns in your game, along with name and colour customisation. * Chat A simple text chat example, send messages between players that login via Network Authenticator. * Common Contains miscellaneous features that are not full examples. * Couch Co-Op Add additional local players to your game, they all share same screen, different controls. Remote joining clients can do the same, allows for a combination of local players vs remote players, such as 2 vs 4, or 1 vs 4 vs 99 (granted you would have to setup 99 different controller/keyboard inputs for this). * Discovery Broadcasts on local network, clients can find servers without needing to input IP address or ports. Another popular use is, it can be adjusted to auto join first broadcasted game thats found (or create a game if none), a feature used often in VR or LAN game types. * Lag Compensation Rollback / Lag Compensation is a standalone, Unity / netcode independent algorithm. This is a simple demo to test it, without Mirror. We want this to be usable in all game engines. The demo intentionally introduces latency so that server / client cubes are at different positions when clicking. * [Multiple Additive Scenes](https://mirror-networking.gitbook.io/docs/manual/examples/multiple-additive-scenes) The Multiple Concurrent Additive Scenes example demonstrates a server additively loading multiple instances of a sub-scene into a main scene at startup, with physics separation, and assigning players to the instances to play matches independently. [NetworkSceneChecker](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-scene-checker) is the key component that makes this example work. * Multiple Matches This example demonstrates how to run a large number of non-physics games concurrently in a single game server instance. This would be most appropriate for Card, Board, Puzzle, and Arcade games where there is no physics involved, just presentation and messaging. While this example is turn-based, real-time games work just as well. * [Pong](https://mirror-networking.gitbook.io/docs/manual/examples/pong) A simple example for "How to build a multiplayer game with Mirror" is Pong. It illustrates the usage of `NetworkManager`, `NetworkManagerHUD`, NetworkBehaviour, NetworkIdentity, `NetworkTransform`, `NetworkStartPosition`and various Attributes. * Rigidbody Benchmark Mass test networked physics. * Rigidbody Physics Test differences between physics and network setups to find what is ideal for your scenario. * [Room System](https://mirror-networking.gitbook.io/docs/manual/examples/room) The Room System example demonstrates how to set up a "staging" scene where players assemble before starting a match. When all players are ready, the server sends them all a message to change scenes (along with the server itself) to the actual game play scene so they all come in at once. Includes fully playable game with a character controller where players collect server-spawned prizes for score. * Snapshot Interpolation Snapshot Interpolation is a standalone, Unity / netcode independent algorithm. This is a simple demo to test it, without Mirror. We want this to be usable in all game engines. * Sync Direction Sync List and Sync Var example, controlled via Client->Server sync direction. * [Tanks](https://mirror-networking.gitbook.io/docs/manual/examples/tanks) This is a simple scene with animated tanks, networked rigidbody projectiles, and NavMesh movement. * Tanks Co-Op Take control of tank Vehicles, spawn as regular player prefab, interact with tank to enter, drive and shoot, exit to continue being regular player. * VR A selection of multiplayer-ready virtual reality examples that use Unitys XR toolkit, allows the use of multiple VR headsets with one setup. [PreviousPickups, Drops, and Child Objectschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects) [NextAdditive Levelschevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/additive-levels) Last updated 2 minutes ago --- # Room | Mirror circle-check The hotel staff gets annoyed if you party in the Lobby, they'll tell you to get a **Room**! Mirror's Room system is intended to be the "next step" after a separate Lobby service, typically a master server with match making and game server launching features. circle-exclamation Note that Mirror's Room system is not designed to allow late joiners / spectators once the game has started. If you need these features, you're better off making your game based on Additive Scenes instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/room#initial-setup) Initial Setup ---------------------------------------------------------------------------------------------------------- The typical setup involves 3 scenes: * Offline scene, generally where a Lobby might be shown from a separate service * Room scene, generally where players of a game instance assemble and ready-up before play starts * Game scene, where the game play actually takes place circle-info To make your own game with the Room system, we have [Script Templates](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) to get you started. 1. Create 3 empty scenes: Offline, Room, Game. You can use your own game scene for Game scene if you already have one. 2. In both the Offline and Room scenes, delete the Directional Light, and change the Clear Flags setting in the Main Camera to Solid Color (to make the default UI easier to see). 3. From the Script Templates, create your own Network Room Manager and Network Room Player scripts. 4. In the Offline scene, create an empty game object called `RoomPlayer` and attach the Network Room Player script you just created, then make a prefab of this object and delete it from the scene. 5. In the Offline scene, create an empty game object called `RoomManager`, and add the Network Room Manager script you just created, and a Network Manager HUD component from the Add Component menu. 6. In the Network Room Manager inspector, assign the following: * Offline scene to the Offline Scene field * Room scene to **both** the Online Scene and Room Scene fields * Game scene to the Gameplay scene field * `RoomPlayer` prefab to the Room Player Prefab field * Your own player prefab to the Player Prefab field 7. Compare your assignments and settings with the inspectors shown in the images below. 8. Add all 3 scenes to Build Settings with Offline scene being first, and build the project. 9. With the Offline scene open, click Play, and then Host button in the HUD 10. Start one or more built clients and click Client in the HUD for each one. 11. When all clients have clicked their respective Ready buttons, the Game scene will be loaded for everyone. 12. In the Game scene, the Host client will see a Return to Room button that will take everyone back to the Room scene to start another game with the same players. Room Player objects do nothing in the Game scene, but are not destroyed so that when returning to the Room scene they'll be intact. [hashtag](https://mirror-networking.gitbook.io/docs/manual/examples/room#next-steps) Next Steps ---------------------------------------------------------------------------------------------------- Review the stubbed out overrides in the Network Room Manager and Network Room Player scripts you created from the templates. They're heavily commented on what they're to be used for. You can turn off the default UI in the Network Room Manager and Network Room Player inspectors by unchecking the Show Room UI checkbox, and then make your own UI for the Room scene. * Suggest looking at how the [Basic example](https://mirror-networking.gitbook.io/docs/manual/examples/basic) is done for the Player UI to see how to make a scene canvas and inject locally instantiated UI parts for each player. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_norIs4h9_Sdq9QEb%252F-MH_nu9J9LrjhUcx3AnI%252Fimage.png%3Falt%3Dmedia%26token%3Dc6c6e005-b4df-462b-9056-0a82777a5c8a&width=768&dpr=3&quality=100&sign=d9cd4e08&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_norIs4h9_Sdq9QEb%252F-MH_nwKGD5AZtrFGNBzE%252Fimage.png%3Falt%3Dmedia%26token%3Da329d0a4-4013-402e-8a02-7532874f9c67&width=768&dpr=3&quality=100&sign=9014092c&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_norIs4h9_Sdq9QEb%252F-MH_nxpRnnjsRNuL8WaL%252Fimage.png%3Falt%3Dmedia%26token%3D2e78b6b2-5ca5-4b50-8218-33a963925736&width=768&dpr=3&quality=100&sign=2f9a59d9&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_norIs4h9_Sdq9QEb%252F-MH_nzJmkK-XGQ8CISwR%252Fimage.png%3Falt%3Dmedia%26token%3D84883d45-ad80-4451-b514-27fda9f3898c&width=768&dpr=3&quality=100&sign=d762a94d&sv=2) [PreviousPongchevron-left](https://mirror-networking.gitbook.io/docs/manual/examples/pong) [NextTankschevron-right](https://mirror-networking.gitbook.io/docs/manual/examples/tanks) Last updated 4 years ago * [Initial Setup](https://mirror-networking.gitbook.io/docs/manual/examples/room#initial-setup) * [Next Steps](https://mirror-networking.gitbook.io/docs/manual/examples/room#next-steps) --- # AWS | Mirror During this section we will focus on using a Windows instance and connecting from a Windows computer. > **NOTE**: AWS requires a payment method/credit card added before being able to use a Windows server. Don't forget to read up on the [free tier limitationsarrow-up-right](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-free-tier.html) . During this example we will be using the free tier of the EC2 option, which gives us the possibility to use a Windows instance (if you have already added a payment method). For more information about which services offer a Free Tier, see [AWS Free Tierarrow-up-right](https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=tier%2312monthsfree&awsf.Free%20Tier%20Categories=categories%23compute) . These are the steps we will go through from start to finish: 1. Account creation 2. Setting up an instance with the EC2 Management Console 3. Configuring the server via RDP (Remote Desktop) 4. Setting up the firewall to allow connections through 5. Testing the connection [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-1-account-creation) 1\. Account Creation ------------------------------------------------------------------------------------------------------------------------------- Go to the [Account creation pagearrow-up-right](https://portal.aws.amazon.com/billing/signup?nc2=h_ct&src=default&redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation#/start) and sign up with your details and payment method (e.g. credit card). Adding the payment method is necessary to run a windows instance on AWS. [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-2-setting-up-an-instance-with-the-ec2-management-console) 2\. Setting up an instance with the EC2 Management Console ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- After setting up your account you should be logged in. Always make sure you're in your correct region so it's a good habit to check in the top right corner. Change it to the closest location to you now. After this click on Services in the top left corner and click on EC2. This will bring you to the EC2 instance dashboard and ready to Launch your instance! Click on **"Launch Instance"**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_sf0cBtgOlw-vaxNo%252Fimage.png%3Falt%3Dmedia%26token%3Da5b99258-a388-487f-9a7f-6c09b13a0e06&width=768&dpr=3&quality=100&sign=fecb08f7&sv=2) There are 7 steps to creating your AWS Instance: 1. Choose an Amazon Machine Image (AMI) 2. Choose Instance Type 3. Configure Instance 4. Add Storage 5. Add Tags 6. Configure Security Group 7. Review ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-1-choose-an-amazon-machine-image) Step 1: Choose an Amazon Machine Image Scroll down until you see the Microsoft Windows Server 2019 Base (take the newest one if this is outdated). Make sure that the option you select has the "Free Tier Eligible" under the icon and click on "Select". ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_sgUIAF9DgbVDx0me%252Fimage.png%3Falt%3Dmedia%26token%3Da0c27675-915c-4d01-a0fd-0f06fdcf7d38&width=768&dpr=3&quality=100&sign=2c0ab0a1&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-2-choose-instance-type) Step 2: Choose Instance Type Make sure you choose the instance type with the "free tier eligible", at the time of writing this is the t2.micro instance. Click on **"Next: Configure Instance Details"**. **Do not** click on Review and Launch. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_shs5MFM0BKVfvwoa%252Fimage.png%3Falt%3Dmedia%26token%3D1ee721bf-2961-4164-86db-e532fc64d4c2&width=768&dpr=3&quality=100&sign=1d7faccc&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-3-configure-instance) Step 3: Configure Instance Nothing has to be changed at this step. Keep it default. Click on **"Next: Add Storage"**. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-4-add-storage) Step 4: Add Storage Nothing has to be changed. Keep it default. The 30GB is more than you need but there will be an error if you choose a lower amount. Keep in mind that you can always click "Previous" if you need to return, you do not need to repeat the entire process if you make a mistake (unless you click Launch at the end). Click on **"Next: Add Tags"** to continue. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-5-add-tags) Step 5: Add Tags Nothing has to be changed. Keep it default. Click on **"Next: Configure Security Groups"** ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-6-configure-security-groups) Step 6: Configure Security Groups > **IMPORTANT STEP** This makes it possible to connect to your instance from outside for: * RDP (needed for this example) * For clients connecting through port 7777 for your Mirror Project. * SSH (if needed) Create a new security group and you can give it your own name and description. Add the following rules: * RDP with source "Anywhere", Description can be whatever but put it as Remote Desktop Program. * Custom TCP Rule with port 7777 and source "Anywhere", Description can be whatever but put it as Mirror. (If KCP is on your NetworkManager, unblock UDP, not TCP) * SSH with source "Anywhere", Description can be whatever but put it as SSH. SSH is not strictly necessary but can be used to remote connect to it through other means than the RDP. You can ignore the warning about the source as this is just a testing environment. In the future you might wish to restrict this but you will almost never know the clients' connection IP's beforehand. Click on **"Next: Review and Launch"** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_skT7DdY1crNVVH7-%252Fimage.png%3Falt%3Dmedia%26token%3De09569f9-8088-46ed-817a-6c658697176a&width=768&dpr=3&quality=100&sign=5ef6989c&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-7-review) Step 7: Review Almost there! Make sure everything is correct and you are using the free tier, then click on **"Launch"**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_smtugkPZfxv29FQ-%252Fimage.png%3Falt%3Dmedia%26token%3D5d0b7329-d614-40be-aa8e-e95b31866679&width=768&dpr=3&quality=100&sign=a00a182e&sv=2) One more thing: A window will pop up asking for your key pair. Just create a new one by selecting the dropdown: **"Create a new key pair"** and give it a name, click on **"Download Key Pair"**. Keep the key file (.PEM File) somewhere secure (To be 100% certain, back it up somewhere). > **YOU CANNOT ACCESS THE CREATED INSTANCE WITHOUT THIS KEY** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_spBzEy_ni4GCSIRO%252Fimage.png%3Falt%3Dmedia%26token%3Dcfe82c73-1cb5-4f43-9f45-b7ef19fbc58b&width=768&dpr=3&quality=100&sign=98b4160b&sv=2) Now you can (finally) click on **"Launch Instances"**! Go back to your EC2 dashboard by clicking on "Services" at the top left and clicking on EC2. Now you see you have "Running Instances: 1". **Click on "Running Instances" to continue**. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_srLaZLCoKogR9H11%252Fimage.png%3Falt%3Dmedia%26token%3D8080b9b0-7703-48f4-b978-94cc2c97324a&width=768&dpr=3&quality=100&sign=a628b1b8&sv=2) > A new instance might take around 5-10 minutes to set up. Refresh the page after 10 minutes if nothing changes. Now you did all this but you want to get ON the dedicated server right? Perfect! The next step will get you up and running! [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-3-configuring-the-server-via-rdp-remote-desktop) 3\. Configuring the server via RDP (Remote Desktop) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Time to get the RDP file so you can start connecting. There are a few things we'll need: 1. RDP file with the key pair added to it 2. Configure RDP file once downloaded to allow getting files from our C: drive or other drives (so you can easily get your zip project) 3. Enter the windows Admin password once you start the RDP file Once you've done this, you should be able to continue using the same RDP file. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#rdp-file-with-the-key-pair-added-to-it) RDP file with the key pair added to it ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_supozUcbAzzwM1L2%252Fimage.png%3Falt%3Dmedia%26token%3Dda242f0e-278c-420c-a55e-4c3151474799&width=768&dpr=3&quality=100&sign=e3d49aef&sv=2) > Get the password **before** clicking Download > **Copy the Password for later** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_sxTxW2e9rS-hsiwM%252Fimage.png%3Falt%3Dmedia%26token%3D0b74606f-5fbd-4a9c-a8b3-e45e567a35ad&width=768&dpr=3&quality=100&sign=aef4e3fc&sv=2) Now click on **"Download Remote Desktop File"**. The RDP file will be downloaded. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_szIVUC7P6gCKYlA9%252Fimage.png%3Falt%3Dmedia%26token%3Df8678043-115a-4640-96f0-a57e0e48cd94&width=768&dpr=3&quality=100&sign=b3104ced&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#configure-rdp-file-for-easy-file-access) Configure RDP file for easy file access Go to your freshly downloaded RDP file and rightclick it and then click "Edit". Go to the third tab "Local sources", at the bottom click "more" under local devices and sources. On the new window select your C: drive or any other drive. This is your own computer your connecting from. For easy file exchange. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_t0gtAcJvgQq-grNm%252Fimage.png%3Falt%3Dmedia%26token%3D0e3a4b44-3aa5-4d8f-a5c7-651f1a013a89&width=768&dpr=3&quality=100&sign=151bff0&sv=2) Perfect! Now you can run the RDP file! The RDP file will ask a password. If you forgot your password you can get it back by rightclicking the instance and clicking on "Get Windows Password". You will be asked to re-enter your key pair (.PEM) file and decrypt the message. Once done you will be able to copy the password. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_t2BnaGi81QRaXAp5%252Fimage.png%3Falt%3Dmedia%26token%3De101ecb4-f393-46dd-a0ba-63ae1588696d&width=768&dpr=3&quality=100&sign=28d4e1d2&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_t46YqrByKyDLqdni%252Fimage.png%3Falt%3Dmedia%26token%3D23ee98cb-510d-4af3-b79a-49d842c0aa69&width=768&dpr=3&quality=100&sign=d87720da&sv=2) There you have it! Now you have your password and Remote Desktop should show you logging into your dedicated server! ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#setting-up-the-firewall-to-allow-connections-through) Setting up the firewall to allow connections through Go to the windows firewall settings, go to the advanced firewall settings and go to inbound rules. **Add a new rule** and choose the port type. Select TCP and enter the 7777 port (or any other if you use another port in Mirror) (If KCP is on your NetworkManager, unblock UDP, not TCP). Continue clicking next and keep things default. Close all the windows when done. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_t5XB4ufVb5bH4YKM%252Fimage.png%3Falt%3Dmedia%26token%3D0446eebd-c5f5-4805-8d87-7a00b4f494f5&width=768&dpr=3&quality=100&sign=189ddfe5&sv=2) AWESOME! You now have everything set up to accept incoming requests on **port 7777**. [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-4-testing-the-connection) 4\. Testing the connection ------------------------------------------------------------------------------------------------------------------------------------------- Before you can (finally) test out your server build of your project you need to get it on the dedicated server! Place your (zipped) server build at the root of your added drive (C: or another) to make it easier to find it fast. Go to **"My Computer"** and because of our previous changes to the RDP we should now see your local drive under "Devices and Drives". Double click it and because you placed your zipped server build on that drive, you should see it immediatly when it's done loading. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_sZwi6YN3ieBcuvWj%252F-MH_t7HWC8JU4VdhVZCZ%252Fimage.png%3Falt%3Dmedia%26token%3D973525eb-6717-48da-bb2c-2aadff368196&width=768&dpr=3&quality=100&sign=688e991d&sv=2) Now unzip the project in a new folder on the dedicated server's desktop and run it. Want to test if it sees the 7777 port is open after you started your Mirror server? Get your IPv4 public IP from the EC2 Management Console from your instance and use it on your client to connect to that IP. Go to [PortCheckerarrow-up-right](https://www.portcheckers.com/) and enter the Dedicated Server IP address and enter port 7777. > NOTE: If you are not running your game / project then the port will be closed. It's only open when the server is running. [PreviousCloud Hosting Guideschevron-left](https://mirror-networking.gitbook.io/docs/hosting/server-hosting) [NextGoogle Cloudchevron-right](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud) Last updated 4 years ago * [1\. Account Creation](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-1-account-creation) * [2\. Setting up an instance with the EC2 Management Console](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-2-setting-up-an-instance-with-the-ec2-management-console) * [Step 1: Choose an Amazon Machine Image](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-1-choose-an-amazon-machine-image) * [Step 2: Choose Instance Type](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-2-choose-instance-type) * [Step 3: Configure Instance](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-3-configure-instance) * [Step 4: Add Storage](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-4-add-storage) * [Step 5: Add Tags](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-5-add-tags) * [Step 6: Configure Security Groups](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-6-configure-security-groups) * [Step 7: Review](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#step-7-review) * [3\. Configuring the server via RDP (Remote Desktop)](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-3-configuring-the-server-via-rdp-remote-desktop) * [RDP file with the key pair added to it](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#rdp-file-with-the-key-pair-added-to-it) * [Configure RDP file for easy file access](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#configure-rdp-file-for-easy-file-access) * [Setting up the firewall to allow connections through](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#setting-up-the-firewall-to-allow-connections-through) * [4\. Testing the connection](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws#id-4-testing-the-connection) --- # Scene GameObjects | Mirror There are two types of networked game objects in Mirror’s multiplayer system: * Those that are created dynamically at runtime * Those that are saved as part of a Scene Game objects that are created dynamically at runtime use the multiplayer Spawning system, and the prefabs they are instantiated from must be registered in the Network Manager’s list of networked game object prefabs. However, networked game objects that you save as part of a Scene (and therefore already exist in the Scene when it is loaded) are handled differently. These game objects are loaded as part of the Scene on both the client and server, and exist at runtime before any spawn messages are sent by the multiplayer system. When the Scene is loaded, all networked game objects in the Scene are disabled on both the client and the server. Then, when the Scene is fully loaded, the Network Manager automatically processes the Scene’s networked game objects, registering them all (and therefore causing them to be synchronized across clients), and enabling them, as if they were spawned at runtime. Networked game objects will not be enabled until a client has requested a Player object. Saving networked game objects in your Scene (rather than dynamically spawning them after the scene has loaded) has some benefits: * They are loaded with the level, so there will be no pause at runtime. * They can have specific modifications that differ from prefabs * Other game object instances in the Scene can reference them, which can avoid you having to use code to finding the game objects and make references to them up at runtime. When the Network Manager spawns the networked Scene game objects, those game objects behave like dynamically spawned game objects. Mirror sends them updates and ClientRPC calls. If a Scene game object is destroyed on the server before a client joins the game, then it is never enabled on new clients that join. When a client connects, the client is sent an ObjectSpawnScene spawn message for each of the Scene game objects that exist on the server, that are visible to that client. This message causes the game object on the client to be enabled, and has the latest state of that game object from the server in it. This means that only game objects that are visible to the client, and not destroyed on the server, are activated on the client. Like regular non-Scene game objects, these Scene game objects are started with the latest state when the client joins the game. [PreviousCustom Spawn Functionschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-spawnfunctions) [NextPickups, Drops, and Child Objectschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects) --- # Network Manager | Mirror The Network Manager is a component for managing the networking aspects of a multiplayer game. It wraps up a lot of useful functionality into a single place, and makes creating, running and debugging multiplayer games as simple as possible. The Network Manager features include: * Game state management * Spawn management * Scene management * Debugging information * Customization [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#getting-started-with-the-network-manager) Getting Started with the Network Manager ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The Network Manager is the core controlling component of a multiplayer game. To get started, create your new Network Manager from the [Script Template](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) included with Mirror, create an empty game object in your starting Scene, and add the newly created Network Manager component. The newly added Network Manager component looks like this: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FDb60jQFBN4xM1XGrToLd%252Fimage.png%3Falt%3Dmedia%26token%3D77083529-6049-4878-a0c0-0ba13736f289&width=768&dpr=3&quality=100&sign=e8dc4d27&sv=2) The Inspector for the Network Manager in the Editor allows you to configure and control many things related to networking. **Note**: You can only ever have one active Network Manager in each scene because it's a singleton. Do not place the Network Manager component on a networked game object (one which has a Network Identity component), because Mirror disables these when the Scene loads. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#transports) Transports ----------------------------------------------------------------------------------------------------------------- Mirror uses a separate component (derived from the Transport class) to connect across the network. The new default Transport is KCP (which uses UDP, not TCP). This design choice of separating the transport into its own component allows game developers to choose the transport that best fits their game needs. Changing transports is as simple as swapping out the component on the Network Manager object and assigning it to the Transport field. Transports are available for TCP, UDP, WebGL, Steam, and many more. Additionally, there's a Multiplex transport that allows for using two transports together on the server, e.g. Telepathy and WebSockets, so that desktop and browser players can play together on the same server seamlessly. See [Transports](https://mirror-networking.gitbook.io/docs/manual/transports) for more information. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#game-state-management) Game State Management --------------------------------------------------------------------------------------------------------------------------------------- A Networking multiplayer game can run in three modes - as a client, as a dedicated server, or as a host which is both a client and a server at the same time. If you’re using the [Network Manager HUD](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud) , it automatically tells the Network Manager which mode to start in, based on which button the player clicks. If you’re writing your own UI that allows the player to start the game, you’ll need to call these from your own code. These methods are: * StartClient * StartServer * StartHost Whichever mode the game starts in (client, server, or host), the Network Address and Transport configuration are used. * In client mode, the game attempts to connect to the network address specified. A fully-qualified domain name (FQDN) can also be used for the Network Address, e.g. "game.example.com". * In server or host mode, the game listens for incoming connections on `localhost` which includes the local network IP address of the server machine. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#spawn-management) Spawn Management ----------------------------------------------------------------------------------------------------------------------------- Use the Network Manager to manage the spawning (networked instantiation) of networked game objects from Prefabs. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNZ2XqTBBSDYNlVZMs%252F-MUNZDp2B02PlyLl7N-N%252Fimage.png%3Falt%3Dmedia%26token%3D76b988fa-e1a0-4dba-aeb6-d152592f37c4&width=768&dpr=3&quality=100&sign=5f666b3e&sv=2) Most games have a Prefab which represents the player, so the Network Manager has a Player Prefab slot. You should assign this slot with your player Prefab. When you have a player Prefab set, a player game object is automatically spawned from that Prefab for each user in the game. This applies to the local player on a hosted server, and remote players on remote clients. You must attach a Network Identity component to the Player Prefab before assigning it to this field. Once you have assigned a Player Prefab, you can start the game as a host and see the player game object spawn. Stopping the game destroys the player game object. If you build and run another copy of the game and connect it as a client to _localhost_, the Network Manager makes another player game object appear. When you stop that client, it destroys that player’s game object. In addition to the Player Prefab, you must also register other prefabs that you want to dynamically spawn during game play with the Network Manager. You can add prefabs to the list shown in the inspector labelled Registered Spawnable Prefabs. You can also register prefabs via code, with the `NetworkClient.RegisterPrefab` method. If you have one Network Manager that is persisted through scenes via Don't Destroy On Load (DDOL), you need to register all prefabs to it which might be spawned in any scene. If you have a separate Network Manager in each scene, you only need to register the prefabs relevant for that scene. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#start-positions) Start Positions --------------------------------------------------------------------------------------------------------------------------- The Network Manager will spawn Player Prefab at their defined transform position and rotation by default, however the Player Spawn Method property allows you to control how start positions are chosen in conjunction with [Network Start Position](https://mirror-networking.gitbook.io/docs/manual/components/network-start-position) components. * Choose Random to spawn players at randomly chosen startPosition options. * Choose Round Robin to cycle through startPosition options in a set list. If the Random or Round Robin modes don’t suit your game, you can customize how the start positions are selected by using code. You can access the available Network Start Position components by the list `NetworkManager.startPositions`, and you can use the helper method `GetStartPosition` on the Network Manager that can be used in an implementation of `OnServerAddPlayer` to find a start position. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#scene-management) Scene Management ----------------------------------------------------------------------------------------------------------------------------- Most games have more than one scene. At the very least, there is usually a title screen or starting menu scene in addition to the scene where the game is actually played. The Network Manager is designed to automatically manage scene state and scene transitions in a way that works for a multiplayer game. There are two slots on the Network Manager inspector for scenes: the Offline Scene and the Online Scene. Dragging scene assets into these slots activates networked Scene Management. When a server or host is started, the Online Scene is loaded. This then becomes the current network scene. Any clients that connect to that server are instructed to also load that scene. The name of this scene is stored in the `networkSceneName` property. When the network is stopped, by stopping the server or host or by a client disconnecting, the offline Scene is loaded. This allows the game to automatically return to a menu scene when disconnected from a multiplayer game. You can also change scenes while the game is active by calling `ServerChangeScene`. This makes all the currently connected clients change Scene too, and updates `networkSceneName` so that new clients also load the new Scene. While networked Scene management is active, any calls to game state management functions such as `StartHost` or `StopClient` can cause scene changes. This applies to the runtime control UI. By setting up scenes and calling these methods, you can control the flow of your multiplayer game. Note that scene change causes all the game objects in the previous scene to be destroyed. You should normally make sure the Network Manager persists between Scenes, otherwise the network connection is broken upon a scene change. To do this, ensure the Don’t Destroy On Load checkbox is ticked in the inspector. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#customization) Customization ----------------------------------------------------------------------------------------------------------------------- There are virtual functions on the `NetworkManager` class that you can customize by creating your own derived class that inherits from `NetworkManager`. When implementing these functions, be sure to take care of the functionality that the default implementations provide. For example, in `OnServerAddPlayer`, the function `NetworkServer.AddPlayer` must be called to activate the player game object for the connection. To make this easier, we've made a set of [Script Templates](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) that have all the overrides stubbed out for you. [PreviousNetwork Identitychevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-identity) [NextNetwork Manager HUDchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-manager-hud) Last updated 2 years ago * [Getting Started with the Network Manager](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#getting-started-with-the-network-manager) * [Transports](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#transports) * [Game State Management](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#game-state-management) * [Spawn Management](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#spawn-management) * [Start Positions](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#start-positions) * [Scene Management](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#scene-management) * [Customization](https://mirror-networking.gitbook.io/docs/manual/components/network-manager#customization) --- # Network Transform | Mirror The Network Transform component synchronizes the position, rotation, and scale of networked game objects across the network. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FcwKghd0kaUglT18AS0Ws%252Fimage.png%3Falt%3Dmedia%26token%3D87995c18-07ef-46a1-99a2-3a215a32c9e0&width=768&dpr=3&quality=100&sign=99fbdd4e&sv=2) Network Transform Component circle-info Mirror currently provides **two** NetworkTransform variations: * Reliable: low bandwidth, same latency as Rpcs/Cmds/etc. * Unreliable: high bandwidth, extremely low latency Use NetworkTransform**Reliable** unless you need super low latency. A game object with a Network Transform component must also have a Network Identity component. When you add a Network Transform component to a game object, Mirror also adds a Network Identity component on that game object if it does not already have one. By default, Network Transform is server-authoritative unless you change the Sync Direction to Client To Server. Client Authority applies to player objects as well as non-player objects that have been specifically assigned to a client, but only for this component. With this enabled, position changes are send from the client to the server. You can use the **Sync Interval** to specify how often it syncs (in seconds). ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-transform#smooth-movement-during-latency-packet-loss-and-jitter) Smooth Movement during Latency, Packet Loss & Jitter `NetworkTransform` sends movement updates every `sendInterval` over the `Unreliable` channel. Network conditions are never ideal, so those updates may come in out of order, delayed or get dropped somewhere on the way. Smooth movement over non-ideal network conditions is one of the more difficult problems in game networking. Our `NetworkTransform` component solves it by using [Snapshot Interpolation](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation) . We recommend reading through the linked chapter to understand it in detail. In short, smooth movement over non-ideal conditions is achieved through buffering. The worse the conditions, the higher the **Buffer Time Multiplier** needs to be. However, the higher it is the longer it buffers too. The total buffer time is calculated by `sendInterval * Buffer Time Multiplier`. It's usually recommended to use a factor of '3'. This means that while you can **increase** the `Buffer Time Multiplier` to make up for worse conditions, you could also **decrease** the `sendInterval` to still keep a reasonably low buffering delay. Our new Network Transform is already used in production by several real world game projects. Check out [this videoarrow-up-right](https://www.youtube.com/watch?v=z2JpT_qLmzk) for a comparison between our old & new **Network Transform** components. circle-info Note: In Newer Mirror versions, sync interval has moved to NetworkManager as "Send Rate". Send rate of 10, would be 0.1 sync interval. [PreviousRemote Statisticschevron-left](https://mirror-networking.gitbook.io/docs/manual/components/remote-statistics) [NextSnapshot Interpolationchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation) Last updated 1 year ago --- # GameObjects | Mirror Networked **GameObjects** are game objects which are controlled and synchronized by Mirror’s networking system. Using synchronized networked game objects, you can create a shared experience for all the players who are playing an instance of your game. They see and hear the same events and actions - even though that may be from their own unique viewpoints within your game. Multiplayer games in Mirror are typically built using Scenes that contain a mix of networked game objects and regular (non-networked) game objects. The networked game objects are those which move or change during gameplay in a way that needs to be synchronized across all users who are playing the game together. Non-networked game objects are those which either don’t move or change at all during gameplay (for example, static obstacles like rocks or fences), or game objects which have movement or changes that don’t need to be synchronized across players (for example, a gently swaying tree or clouds passing by in the background of your game). A networked game object is one which has a Network Identity component attached. However, a Network Identity component alone is not enough for your game object to be functional and active in your multiplayer game. The Network Identity component is the starting point for synchronization, and it allows the Network Manager to synchronize the creation and destruction of the game object, but other than that, it does not specify _which properties_ of your game object should be synchronized. What exactly should be synchronized on each networked game object depends on the type of game you are making, and what each game object’s purpose is. Some examples of what you might want to synchronize are: * The position and rotation of moving game objects such as the players and non-player characters. * The animation state of an animated game object * The value of a variable, for example how much time is left in the current round of a game, or how much energy a player has. Some of these things can be automatically synchronized by Mirror. The synchronized creation and destruction of networked game objects is managed by the NetworkManager, and is known as Spawning. You can use the Network Transform component to synchronize the position and rotation of a game object, and you can use the Network Animator component to synchronize the animation of a game object. To synchronize other properties of a networked game object, you need to use scripting. See State Synchronization for more information about this. [PreviousNetwork Messageschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/communications/network-messages) [NextPlayer Game Objectschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/player-gameobjects) Last updated 5 years ago --- # Network Room Manager | Mirror **Please see the Room example in the Examples folder in your Mirror folder.** The Network Room Manager is a specialized type of [Network Manager](https://mirror-networking.gitbook.io/docs/manual/components/network-manager) that provides a multiplayer room before entering the main play scene of the game. It allows you to set up a network with: * A maximum player limit * Automatic start when all players are ready * Game is locked after start, preventing late joiners * Customizable ways for players to choose options while in room There are two types of player objects with the Network Room Manager: **Room Player Prefab** * One for each player * Created when client connects, or player is added * Persists until client disconnects * Holds ready flag and configuration data * Handles commands in the room * Must use the [Network Room Player](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player) component **Player Prefab** * One for each player * Created when game scene is started * Destroyed when leaving game scene * Handles commands in the game ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNaH5QclCmWjXqmR8a%252F-MUNaIBdMQuPniRag5rq%252Fimage.png%3Falt%3Dmedia%26token%3D710fc580-0b1d-4544-9191-ab93158d83d3&width=768&dpr=3&quality=100&sign=140d367&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#properties) Properties ---------------------------------------------------------------------------------------------------------------------- * **Show Room GUI** Show the default OnGUI controls for the room. * **Min Players** Minimum number of players needed to start a game. * **Room Player Prefab** The prefab to create for players when they enter the room (requires Network Room Player component). * **Room Scene** The scene to use for the room. * **Gameplay Scene** The scene to use for main game play. * **pendingPlayers** List that holds players that are ready to start playing. * **roomSlots** List that manages the slots for connected clients in the room. * **allPlayersReady** Bool indicating if all players are ready to start playing. This value changes as players invoke `CmdChangeReadyState` indicating true or false, and will be set false when a new client connects. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#methods) Methods ---------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#server-virtual-methods) Server Virtual Methods ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#client-virtual-methods) Client Virtual Methods [PreviousNetwork Lerp Rigidbodychevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-lerp-rigidbody) [NextNetwork Room Playerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-room-player) Last updated 2 years ago * [Properties](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#properties) * [Methods](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#methods) * [Server Virtual Methods](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#server-virtual-methods) * [Client Virtual Methods](https://mirror-networking.gitbook.io/docs/manual/components/network-room-manager#client-virtual-methods) Copy public virtual void OnRoomStartHost() { } public virtual void OnRoomStopHost() { } public virtual void OnRoomStartServer() { } public virtual void OnRoomStopServer() { } public virtual void OnRoomServerConnect(NetworkConnectionToClient conn) { } public virtual void OnRoomServerDisconnect(NetworkConnectionToClient conn) { } public virtual void OnRoomServerSceneChanged(string sceneName) { } public virtual GameObject OnRoomServerCreateRoomPlayer(NetworkConnectionToClient conn) { return null; } public virtual GameObject OnRoomServerCreateGamePlayer(NetworkConnectionToClient conn, GameObject roomPlayer) { return null; } public virtual void OnRoomServerAddPlayer(NetworkConnectionToClient conn) { } public virtual bool OnRoomServerSceneLoadedForPlayer(NetworkConnectionToClient conn, GameObject roomPlayer, GameObject gamePlayer) { return true; } public virtual void OnRoomServerPlayersReady() { } public virtual void OnRoomServerPlayersNotReady() { } public virtual void ReadyStatusChanged() { } Copy public virtual void OnRoomClientEnter() { } public virtual void OnRoomClientExit() { } public virtual void OnRoomClientConnect() { } public virtual void OnRoomClientDisconnect() { } public virtual void OnRoomStartClient() { } public virtual void OnRoomStopClient() { } public virtual void OnRoomClientSceneChanged() { } [Obsolete("OnRoomClientReady is obsolete, use OnRoomClientDisconnect or OnRoomStopClient.")] public virtual void OnRoomClientAddPlayerFailed() {} public virtual void OnGUI() { } --- # Player Game Objects | Mirror Mirror handles player game objects differently to non-player game objects. When a new player joins the game (when a new client connects to the server), that player’s game object becomes a “local player” game object on the client of that player, and Unity associates the player’s connection with the player’s game object. Unity associates one player game object for each person playing the game, and routes networking commands to that individual game object. A player cannot invoke a command on another player’s game object, only their own. The NetworkBehaviour class (which you derive from to [create your network scripts](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) ) has a property called isLocalPlayer. On each client’s player game object, Mirror sets that property to true on the NetworkBehaviour script, and invokes the OnStartLocalPlayer() callback. This means each client has a different game object set up like this, because on each client a different game object is the one that represents the local player. The diagram below shows two clients and their local players. Only the player game object that is “yours” (from your point of view as the player) has the `isLocalPlayer` flag set. Usually, you should set this flag in script to determine whether to process input, whether to make the camera track the game object, or do any other client-side things that should only occur for the player belonging to that client. Player game objects represent the player (that is, the person playing the game) on the server, and have the ability to run commands from the player’s client. These commands are secure client-to-server remote procedure calls. In this server-authoritative system, other non-player server-side game objects cannot receive commands directly from client-side game objects. This is both for security, and to reduce the complexity of building your game. By routing all incoming commands from users through the player game object, you can ensure that these messages come from the right place, the right client, and can be handled in a central location. The Network Manager adds a player every time a client connects to the server. In some situations, though, you might not want to add players until an input event happens - such as a user pressing a “start” button on the controller. To disable automatic player creation, navigate to the Network Manager component’s Inspector and untick the Auto Create Player checkbox. The diagram below shows two clients and their local players: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fddf28174da8bafffd94e5d55128f6346269d7ff9.png%3Fgeneration%3D1600508382464064%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=8fedbdc3&sv=2) Network Players and Clients [PreviousGameObjectschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects) [NextCustom Character Spawningchevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning) Last updated 2 years ago --- # NetworkManager Callbacks | Mirror circle-info See also [NetworkManagerarrow-up-right](https://storage.googleapis.com/mirror-api-docs/html/d7/d5a/class_mirror_1_1_network_manager.html) in the API Reference. There are a number of events that can occur over the course of the normal operation of a multiplayer game, such as the host starting up, a player joining, or a player leaving. Each of these possible events has an associated callback that you can implement in your own code to take action when the event occurs. To do this for the `NetworkManager`, you need to create your own script which inherits from `NetworkManager`. You can then override the virtual methods on `NetworkManager` with your own implementation of what should happen when the given event occurs. This page lists all the virtual methods (the callbacks) that you can implement on the `NetworkManager`, and when they occur. The callbacks that occur, and the order they occur, vary slightly depending on which mode your game is running in, so each mode’s callbacks are listed separately below. A game can be running in one of three modes, host, client, or server-only. The callbacks for each mode are listed below: [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks#host-mode) Host Mode: ------------------------------------------------------------------------------------------------------------------------------------ When the host is started: * `OnStartServer` * `OnStartHost` * `OnServerConnect` * `OnStartClient` * `OnClientConnect` * `OnServerSceneChanged` * `OnServerReady` * `OnServerAddPlayer` * `OnClientChangeScene` * `OnClientSceneChanged` When a client connects: * `OnServerConnect` * `OnServerReady` * `OnServerAddPlayer` When a client disconnects: * `OnServerDisconnect` When the host is stopped: * `OnStopHost` * `OnServerDisconnect` * `OnStopClient` * `OnStopServer` [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks#client-mode) Client Mode --------------------------------------------------------------------------------------------------------------------------------------- When the client starts: * `OnStartClient` * `OnClientConnect` * `OnClientChangeScene` * `OnClientSceneChanged` When the client stops: * `OnStopClient` * `OnClientDisconnect` [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks#server-mode) Server Mode --------------------------------------------------------------------------------------------------------------------------------------- When the server starts: * `OnStartServer` * `OnServerSceneChanged` When a client connects: * `OnServerConnect` * `OnServerReady` * `OnServerAddPlayer` When a client disconnects: * `OnServerDisconnect` When the server stops: * `OnStopServer` [PreviousRemote Actionschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) [NextNetworkBehaviour Callbackschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks) Last updated 2 years ago * [Host Mode:](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks#host-mode) * [Client Mode](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks#client-mode) * [Server Mode](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks#server-mode) --- # Network Discovery | Mirror Suppose your are next to a friend. He starts a game in host mode and you want to join him. How will your phone locate his? Finding out his IP address is not exactly intuitive or something kids can do. To solve this problem you can use Network Discovery. When your game starts, it sends a message in your current network asking "Is there any server available?". Any server within the same network will reply and provide information about how to connect to it. Mirror comes with a simple implementation of Network Discovery you can simply use in your game. It also provides a way for you to extend it so that you can pass additional data during the discovery phase. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNTq5mM_W3Cao1oP75%252F-MUNTwo2O1XPiHRrv7b7%252Fimage.png%3Falt%3Dmedia%26token%3D2cc91726-ea9a-484c-abc4-547eaeff8a98&width=768&dpr=3&quality=100&sign=ffd329fa&sv=2) NetworkDiscovery and NetworkDiscoveryHUD components are included, or you can make your own from a [ScriptTemplate](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) . Network Discovery uses a UDP broadcast on the LAN enabling clients to find the running server and connect to it. When a server is started, it listens on the UDP Broadcast Listen Port for requests from clients and returns a connection URI that clients apply to their transport. You can adjust how often the clients send their requests out to find a server in seconds with the Active Discovery Interval. The Server Found event must be assigned to a handler method, e.g. the OnDiscoveredServer method of NetworkDiscoveryHUD. In the NetworkDiscoveryHUD, the NetworkDiscovery component should be assigned automatically. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-discovery#quick-start) Quick Start --------------------------------------------------------------------------------------------------------------------- To use Network Discovery follow these steps: 1. Create a gameobject with a NetworkManager if you have not done so already 2. Do not add a NetworkManagerHUD. Discovery has a different UI component. 3. Add a NetworkDiscoveryHUD component to the NetworkManager gameobject. A NetworkDiscovery component will be automatically added and wired up to your HUD. 4. Add a player to the NetworkManager if you have not done so. 5. Build and run a standalone version 6. Click on Start Host 7. Start play mode in the editor and click on Find Servers 8. The editor should find the standalone version and display a button 9. Click on the button to connect to it. The NetworkDiscoveryHUD is provided as a simple and quick way to get started, but you will probably want to replace it with your own user interface. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-discovery#custom-network-discovery) Custom Network Discovery ----------------------------------------------------------------------------------------------------------------------------------------------- You can completely replace the user interface by adding your own interface (typically Unity UI based) instead of the default NetworkDiscoveryHUD. You do still need the NetworkDiscovery component to do the heavy lifting. Sometimes you want to provide more information in the discovery messages. Some use cases could include: * The client can show if the server is in PvP or PvE mode * The client can show how full the servers are. * The client can show the ping to each server so the player can chose the fastest server * The client can show the language * The client can show if the server is password protected To do this, we've provided a [Template](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) , so from the Assets menu, click Create > Mirror > Network Discovery. This will create a script in your project with 2 empty message classes and a custom NetworkDiscovery class that inherits from NetworkDiscoveryBase and has all the override methods included and documented for you. The message classes define what is sent between the client and server. As long as you keep your messages simple using the [data types](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) that Mirror can serialize, you won't need to write custom serializers for them. The custom NetworkDiscovery class contains the overrides for handling the messages above. You may want to refer to the NetworkDiscovery.cs script in the Components/Discovery folder to see how these should be implemented. circle-info Note: Take into account any anti virus/firewall blocking, along with additional settings for your particular platform (broadcast address iOS, Network Discovery sharing settings to on in Windows etc). [PreviousNetwork Behaviourchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour) [NextNetwork Identitychevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-identity) Last updated 2 years ago * [Quick Start](https://mirror-networking.gitbook.io/docs/manual/components/network-discovery#quick-start) * [Custom Network Discovery](https://mirror-networking.gitbook.io/docs/manual/components/network-discovery#custom-network-discovery) Copy public class DiscoveryRequest : NetworkMessage { public string language="en"; // Add properties for whatever information you want sent by clients // in their broadcast messages that servers will consume. } public class DiscoveryResponse : NetworkMessage { enum GameMode {PvP, PvE}; // you probably want uri so clients know how to connect to the server public Uri uri; public GameMode GameMode; public int TotalPlayers; public int HostPlayerName; // Add properties for whatever information you want the server to return to // clients for them to display or consume for establishing a connection. } Copy public class NewNetworkDiscovery: NetworkDiscoveryBase { #region Server protected override void ProcessClientRequest(DiscoveryRequest request, IPEndPoint endpoint) { base.ProcessClientRequest(request, endpoint); } protected override DiscoveryResponse ProcessRequest(DiscoveryRequest request, IPEndPoint endpoint) { // TODO: Create your response and return it return new DiscoveryResponse(); } #endregion #region Client protected override DiscoveryRequest GetRequest() { return new DiscoveryRequest(); } protected override void ProcessResponse(DiscoveryResponse response, IPEndPoint endpoint) { // TODO: a server replied, do something with the response such as invoking a unityevent } #endregion } --- # Serialization | Mirror This page goes into depth about Serialization, for the basics see [DataTypes](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) . Mirror creates Serialize and Deserialize functions for types using Weaver. Weaver edits dll after unity compiles them using Mono.Cecil. This allows mirror to have a lot of complex features like SyncVar, ClientRpc and Message Serialization without the user needed to manually set everything up. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#rules-and-tips) Rules and tips ------------------------------------------------------------------------------------------------------------------- There are some rules and limits for what Weaver can do. Some features add complexity and are hard to maintain so have not been implemented. These features are not impossible to implement and could be added if there is a high demand for them. * You should be able to write Custom Read/Write functions for any type, and Weaver will use. * This means if there is a unsupported type like `int[][]` creating a custom Read/Write function will allow you to sync `int[][]` in SyncVar/ClientRpc/etc * If you have a type that has a field that is not able to be Serialize, you can mark that field with `[System.NonSerialized]` and weaver will ignore it ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#unsupported-types) Unsupported Types Some of these types are unsupported due to the complexity they would add, as mentioned above. > NOTE: Types in this list can have custom writers. * Jagged and Multidimensional array * Types that Inherit from `UnityEngine.Component` * `UnityEngine.Object` * `UnityEngine.ScriptableObject` * Generic Types, eg `MyData` * Custom Read/Write must declare T, eg `MyData` * Interfaces * Types that references themselves ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#built-in-read-write-functions) Built-in Read Write Functions Mirror provides some built-in Read/Write Functions. They can be found in `NetworkReaderExtensions` and `NetworkWriterExtensions`. This is a Non-compete list of types that have built-in functions, check the classes above to see the full list. * Most [C# primitive typesarrow-up-right](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/built-in-types) * Common Unity structs * Vector3 * Quaternion * Rect * Ray * Guid * NetworkIdentity, GameObject, Transform ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#networkidentity-gameobject-transform) NetworkIdentity, GameObject, Transform The `netId` of the Object is sent over the network, and the Object with the same `netId` is returned on the other side. If the `netId` is zero or an object is not found then `null` will be returned. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#generated-read-write-functions) Generated Read Write Functions Weaver will Generate Read Write functions for * Classes or Structs * Enums * Arrays * eg `int[]` * ArraySegments * eg `ArraySegment` * Lists * eg `List` #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#classes-and-structs) Classes and Structs Weaver will Read/Write every public field in the type, unless the field is marked with `[System.NonSerialized]`. If there is an unsupported type in the class or struct Weaver will fail to make Read/Write functions for it. > NOTE: Weaver does not check properties #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#enums) Enums Weaver will use the underlying Type of an enum to Read and Write them. By default this is `int`. For example `Switch` will use the `byte` Read/Write functions to be Serialized #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#collections) Collections Weaver will Generate writes for the collections listed above. Weaver will use the elements Read/Write function. The element must have a Read/Write function so must be a supported type, or have a custom Read/Write function. For example: * `float[]` is a supported type because Mirror has a built-in Read/Write function for `float`. * `MyData[]` is a supported type as Weaver is able to generate a Read/Write function for `MyData` [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#adding-custom-read-write-functions) Adding Custom Read Write functions ----------------------------------------------------------------------------------------------------------------------------------------------------------- Read Write functions are static methods in the form of: It is best practice to make Read/Write functions [extension methodsarrow-up-right](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods) so they can be called like `writer.WriteMyType(value)`. It is a good idea to call them `ReadMyType` and `WriteMyType` so it is obvious what type they are for. However the name of the function doesn't matter, weaver should be able to find it no matter what it is called. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#properties-example) Properties Example Weaver wont write properties, but a custom writer can be used to send them over the network. This can be useful if you want to have private set for your properties #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#unsupported-type-example) Unsupported type Example Rigidbody is an unsupported type because it inherits from `Component`. But a custom writer can be added so that it is synced using a NetworkIdentity if one is attached. Above are functions for `MyCollision`, but instead you could add functions for `Rigidbody` and let weaver would generate a writer for `MyCollision`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#debugging) Debugging --------------------------------------------------------------------------------------------------------- You can use tools like [ILSpyarrow-up-right](https://github.com/icsharpcode/ILSpy) and [dnSpyarrow-up-right](https://github.com/0xd4d/dnSpy) to view the complied code after Weaver has altered it. This can help to understand and debug what Mirror and Weaver does. [PreviousData typeschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) [NextSynchronizationchevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization) Last updated 4 years ago * [Rules and tips](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#rules-and-tips) * [Unsupported Types](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#unsupported-types) * [Built-in Read Write Functions](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#built-in-read-write-functions) * [NetworkIdentity, GameObject, Transform](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#networkidentity-gameobject-transform) * [Generated Read Write Functions](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#generated-read-write-functions) * [Adding Custom Read Write functions](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#adding-custom-read-write-functions) * [Debugging](https://mirror-networking.gitbook.io/docs/manual/guides/serialization#debugging) Copy public enum Switch : byte { Left, Middle, Right, } Copy public struct MyData { public int someValue; public float anotherValue; } Copy public static void WriteMyType(this NetworkWriter writer, MyType value) { // write MyType data here } public static MyType ReadMyType(this NetworkReader reader) { // read MyType data here } Copy public struct MyData { public int someValue { get; private set; } public float anotherValue { get; private set; } public MyData(int someValue, float anotherValue) { this.someValue = someValue; this.anotherValue = anotherValue; } } public static class CustomReadWriteFunctions { public static void WriteMyType(this NetworkWriter writer, MyData value) { writer.WriteInt32(value.someValue); writer.WriteSingle(value.anotherValue); } public static MyData ReadMyType(this NetworkReader reader) { return new MyData(reader.ReadInt32(), reader.ReadSingle()); } } Copy public struct MyCollision { public Vector3 force; public Rigidbody rigidbody; } public static class CustomReadWriteFunctions { public static void WriteMyCollision(this NetworkWriter writer, MyCollision value) { writer.WriteVector3(value.force); NetworkIdentity networkIdentity = value.rigidbody.GetComponent(); writer.WriteNetworkIdentity(networkIdentity); } public static MyCollision ReadMyCollision(this NetworkReader reader) { Vector3 force = reader.ReadVector3(); NetworkIdentity networkIdentity = reader.ReadNetworkIdentity(); Rigidbody rigidBody = networkIdentity != null ? networkIdentity.GetComponent() : null; return new MyCollision { force = force, rigidbody = rigidBody, }; } } Copy public static class CustomReadWriteFunctions { public static void WriteRigidbody(this NetworkWriter writer, Rigidbody rigidbody) { NetworkIdentity networkIdentity = rigidbody.GetComponent(); writer.WriteNetworkIdentity(networkIdentity); } public static Rigidbody ReadRigidbody(this NetworkReader reader) { NetworkIdentity networkIdentity = reader.ReadNetworkIdentity(); Rigidbody rigidBody = networkIdentity != null ? networkIdentity.GetComponent() : null; return rigidBody; } } --- # SyncEvent (Obsolete) | Mirror circle-exclamation SyncEvents have been removed in version 18.0.0, see this [Issuearrow-up-right](https://github.com/vis2k/Mirror/pull/2178) for more information. This is an attribute that can be put on events in NetworkBehaviour classes to allow them to be invoked on client when the event is called on the server. SyncEvent events are called by user code on the server, and then invoked on corresponding client objects on clients connected to the server. The arguments to the Event call are serialized across the network, so that the client event is invoked with the same values as the method on the server. These events must begin with the prefix "Event". Copy using UnityEngine; using Mirror; public class DamageClass : NetworkBehaviour { public delegate void TakeDamageDelegate(int amount, float dir); [SyncEvent] public event TakeDamageDelegate EventTakeDamage; [Command] public void CmdDoMe(int val) { EventTakeDamage(val, 1.0f); } } public class Other : NetworkBehaviour { public DamageClass damager; int health = 100; void Start() { if (NetworkClient.active) damager.EventTakeDamage += TakeDamage; } public void TakeDamage(int amount, float dir) { health -= amount; } } SyncEvents allow networked actions to be propagated to other scripts attached to the object. In the example above, the Other class registers for the TakeDamage event on the DamageClass. When the event happens on the DamageClass on the server, the TakeDamage() method will be invoked on the Other class on the client object. This allows modular network aware systems to be created, that can be extended by new scripts that respond to the events generated by them. [PreviousSyncVar Hookschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvar-hooks) [NextSyncListschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) Last updated 5 years ago --- # Network Messages | Mirror For the most part we recommend the high level [Commands and RPC](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) calls and [SyncVar](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars) , but you can also send low level network messages. This can be useful if you want clients to send messages that are not tied to game objects, such as logging, analytics or profiling information. There is a public interface called NetworkMessage that you can extend to make serializable network message structs. Serialize and Deserialize methods are automatically generated for network messages by Mirror, and they can efficiently handle any [supported mirror type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) , but if you need to you can implement your own serialization methods by following our [serialization guide](https://mirror-networking.gitbook.io/docs/manual/guides/serialization) . Some other useful tips for implementing low-level messages: * Make sure all your members are public fields. Weaver doesn't serialize properties. * If you need classes or complex containers such as `List` and `Dictionary`, you must implement the Read and Write methods yourself. To send a message, use the `Send()` method on the NetworkClient, NetworkServer, and NetworkConnection classes, which all work the same way using a message struct that is derived from NetworkMessage. The code below demonstrates how to send and handle a message: To declare a custom network message class and use it: Copy using UnityEngine; using Mirror; public class Scores : MonoBehaviour { public struct ScoreMessage : NetworkMessage { public int score; public Vector3 scorePos; public int lives; } public void SendScore(int score, Vector3 scorePos, int lives) { ScoreMessage msg = new ScoreMessage() { score = score, scorePos = scorePos, lives = lives }; NetworkServer.SendToAll(msg); } public void SetupClient() { NetworkClient.RegisterHandler(OnScore); NetworkClient.Connect("localhost"); } public void OnScore(ScoreMessage msg) { Debug.Log("OnScoreMessage " + msg.score); } } [PreviousNetworkBehaviour Callbackschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks) [NextGameObjectschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects) Last updated 2 years ago --- # Google Cloud | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#google-cloud-services) Google Cloud Services ----------------------------------------------------------------------------------------------------------------------------------------- This guide will explain how to set up a Linux server running on [Google Cloudarrow-up-right](https://cloud.google.com/) . Google cloud offers $300 free credits to new users for a limited time, and it also have "Always free products". See [overviewarrow-up-right](https://cloud.google.com/free) and [docsarrow-up-right](https://cloud.google.com/free/docs/gcp-free-tier) for more information. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#before-you-begin) Before you begin 1. In the Cloud Console, on the project selector page, select or create a Cloud project. > Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project. [**Go to the project selector page**arrow-up-right](https://console.cloud.google.com/projectselector2/home/dashboard) 1. You may need to enable billing for your Google Cloud project. If you have free credits (see above) then these will be used first. [Learn how to confirm billing is enabled for your project.arrow-up-right](https://cloud.google.com/billing/docs/how-to/modify-project) ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#setting-up-a-new-server) Setting up a new Server Start by creating and configuring a new Compute Engine instance. 1. In the Cloud Console, go to the VM instances page: [**Go to the VM instances page**arrow-up-right](https://console.cloud.google.com/compute/instances) If this is your first instance you will see a dialog prompting you to create a new virtual machine ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fe693137a858ff9a06c5b0a986f4a53cd2fdb9365.jpg%3Fgeneration%3D1600508396174978%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=66882749&sv=2) create new 1. Click Create to get started. 2. On the Create an instance page, configure your instance as follows: * Name your instance. This tutorial uses the instance name `mirror-instance-demo` throughout. * Select the region and zone in which you want your instance to be hosted. This tutorial uses the region `us-central1 (Iowa)` and the zone `us-central1-a` throughout. * Machine configuration depends on the size of your game. For a simple example we can use a small server. * select `N1` for series * select `f1-micro` for machine type * In the Boot disk section, click Change. The Boot disk dialog will pop up. * Change the disk type to SSD Persistent Disk. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fe86b20f387030f40154be0c68ca30685c30b90a1.jpg%3Fgeneration%3D1600508395618284%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=8579e079&sv=2) create instance with name and region 1. Boot disk can be left as default `10gb standard persistent disk` with `Debian GNU/Linux 9 (stretch)` for this tutorial. You may want to change it to best fit your needs. You can instead use an ssd or increase its size, however this will increase the monthly cost. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F73b84bca8f9c245e34f58223aa3077d45e31a107.jpg%3Fgeneration%3D1600508394569939%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=d0b0ac78&sv=2) 03Boot disk > Note: The monthly estimate should be shown at the top right next to `Name` 1. To configure Network settings first example the `Management, security, disks, networking, solo tenancy` section, then click on the `Networking` tab. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fc9f1c893bd6f524c76fd4cf1ce8baea13cb0612b.jpg%3Fgeneration%3D1600508395369550%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=28e2ceb3&sv=2) expand network settings 1. Set a Network tag, this will allow you to set up firewall rules later on. This tutorial use `mirror-demo` as the tag ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F7bd8caa02fdf9ca74441c17ab21cf63f9f16be68.jpg%3Fgeneration%3D1600508394399316%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=6a4c2328&sv=2) set network tag 1. Set up a static IP address for your instance a) Under **Network interfaces** click on `default` and it will bring up a config menu b) Select the **External IP** dropdown and select `Create IP address` c) Enter a name for this ip and press **Reserve**. For this tutorial we will use `mirror-demo-ip` ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fb9738ea8aacc002e6ff16bb868f8cbd0f8ea0061.jpg%3Fgeneration%3D1600508395274656%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=1ddb9206&sv=2) reserve ip address 1. Create your instance. Press the **Create** button at the bottom of the page to finish set up and create your instance ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#configure-firewall) Configure Firewall This will allow other people to connect to your server using its IP and port 1. In the Cloud Console, go to the Firewall page. [**Go to the Firewall page**arrow-up-right](https://console.cloud.google.com/networking/firewalls/list) 1. Click Create firewall rule. 2. On the Create a firewall rule page, fill out the form as follows: * Name: `mirror-demo-rule` * Target tags: `mirror-demo` * Source filter: IP ranges * Source IP ranges: 0.0.0.0/0 * Protocols or ports: Select tcp, and then enter port 7777 into the field provided. > note tcp and port 7777 is default settings for telepathy, if you are using a different transport you will need to find out what settings that uses. > > If KCP is on your NetworkManager, unblock UDP, not TCP. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fbc0804b29cf300d4c868a3e3cfbdf8e0627212e3.jpg%3Fgeneration%3D1600508396088549%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=da21ba91&sv=2) Create network rule 1. Press **Create** to confirm setting and create the rule. ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#connect-to-your-new-instance) Connect to your new instance Once your instance has finished being created you can press the **SSH** button to connect to your instance in your web browser ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F61c367de2ef216d09a66d07d672c7813e472a64e.jpg%3Fgeneration%3D1600508396493076%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=a43b40b4&sv=2) connect to instance ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#setting-up-the-linux-instance) Setting up the linux instance When you first connect you will need to set up a few things 1. First update the list of packages 1. Install `screen` and `unzip` `screen` allows you to have multiple terminals, allows you do do other stuff while your game is running `unzip` unzips can be used to extract files from a ZIP file after you upload it to the instance ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F7344ffea05f8de3e7344c915f4fab077e37c1277.jpg%3Fgeneration%3D1600508395058425%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=7d503ddb&sv=2) 09update and install packages ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#build-your-game) Build your game Build your game with Target Platform `Linux` and **Server Build** ticked ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F0cd5df50004cf82f9e179c0781b23a9a2dcdaebd.jpg%3Fgeneration%3D1600508394830177%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=c9482359&sv=2) Server build ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#upload-and-extract-your-game) Upload and extract your game Once you have built your game zip the folder so that you can upload it to your server. In the SSH connection window click on the settings cogwheel and select **Upload File** then find and select your zipped build folder. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fb628c77b3d3e33c4902a606affba6178b647cbb3.jpg%3Fgeneration%3D1600508396587658%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=2b1ca32b&sv=2) Upload a file This should upload the game folder to the home directory. If you need to go to the home directory you can use: > Note: the destination will be `/home/username` where username should be the cloud account you are logged into. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F0df81132a524cf3a19e0377441c4d472a6de5a00.jpg%3Fgeneration%3D1600508395835031%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=6749be2a&sv=2) Uploading Once your file has finished upload you can extract the files ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#run-server) Run server 1. Move into game folder 1. Mark game as executable You should now be able to run your game server! The following is optional but will most likely be useful 1. Start your server in a detached screen The parts of the command above: * `screen -d -m` will create the new terminal in detached mode * `-S mirrorServer` name of the screen * `./mirror-demo.x86_64` your game server file * `-logfile ~/server.log` unity argument for log file location, this will create a log file in the home directory 1. Create start file so you can start your server the same way each time a) create `start.sh` b) mark as executable 2. Run your server #### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#using-screen) Using Screen Here are a few useful commands for using `screen` * List active screens * Attach to existing screen, * process-id is show when calling `screen -ls` * screen name is given by `-S` when creating the screen, for this tutorial it was `mirrorServer` * Detach from screen press `CTRL A + D` * Stop your game Once attached to a screen you can press `CTRL + C` to stop the process, this will stop your game and close the screen #### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#view-log-files) View log files You can use the `-logfile ~/path/to/log.log` argument for Unity when starting your game server. This will cause the logs to be written to a file instead of to the terminal. This will means recent logs wont show up in `screen -r`. * you can use the `tail` command to view the the end of the log file * you can use the `-n` argument to set how many lines to show * you can use the `-f` argument follow the end of the file stream showing you any new logs that are written to the file in real time. You will need to press `CTRL + C` to exit follow mode ### [hashtag](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#clean-up-after-tutorial) Clean up after tutorial If you used an existing project you will need to delete the following: * VM instance * Firewall rule If you have created a new project you should be able to just delete the project. [**Go to the Manage resources page**arrow-up-right](https://console.cloud.google.com/iam-admin/projects) [PreviousAWSchevron-left](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/aws) [NextOracle Free Tierchevron-right](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/oracle-free-tier) Last updated 2 years ago * [Google Cloud Services](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#google-cloud-services) * [Before you begin](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#before-you-begin) * [Setting up a new Server](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#setting-up-a-new-server) * [Configure Firewall](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#configure-firewall) * [Connect to your new instance](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#connect-to-your-new-instance) * [Setting up the linux instance](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#setting-up-the-linux-instance) * [Build your game](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#build-your-game) * [Upload and extract your game](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#upload-and-extract-your-game) * [Run server](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#run-server) * [Clean up after tutorial](https://mirror-networking.gitbook.io/docs/hosting/server-hosting/google-cloud#clean-up-after-tutorial) Copy sudo apt-get update Copy sudo apt-get install -y screen unzip Copy cd ~ Copy unzip ./mirror-demo.zip Copy cd mirror-demo Copy chmod +x ./mirror-demo.x86_64 Copy screen -d -m -S mirrorServer ./mirror-demo.x86_64 -logfile ~/server.log Copy echo "screen -d -m -S mirrorServer ./mirror-demo.x86_64 -logfile ~/server.log" > ./start.sh Copy chmod +x ./start.sh Copy ./start.sh Copy screen -ls Copy screen -r Copy tail -n 50 ./server.log --- # SyncVars | Mirror SyncVars are properties of classes that inherit from NetworkBehaviour, which are synchronized from the server to clients. When a game object is spawned, or a new player joins a game in progress, they are sent the latest state of all SyncVars on networked objects that are visible to them. Use the `SyncVar` custom attribute to specify which variables in your script you want to synchronize. The state of SyncVars is applied to game objects on clients before `OnStartClient()` is called, so the state of the object is always up-to-date inside `OnStartClient()`. SyncVars can use any [type supported by Mirror](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) . You can have up to 64 SyncVars on a single NetworkBehaviour script, including SyncLists (see next section, below). The server automatically sends SyncVar updates when the value of a SyncVar changes, so you do not need to track when they change or send information about the changes yourself. Changing a value in the inspector will not trigger an update. > The [SyncVar hook](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvar-hooks) > attribute can be used to specify a method to be called when the SyncVar changes value on the client. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars#syncvar-example) SyncVar Example -------------------------------------------------------------------------------------------------------------------------------- Let's say we have a networked object with a script called Enemy: Copy public class Enemy : NetworkBehaviour { [SyncVar] public int health = 100; void OnMouseUp() { if (NetworkClient.localPlayer.TryGetComponent(out PlayerController pc)) pc.currentTarget = gameObject; } } The `PlayerController` might look like this: In this example, when a Player clicks on an Enemy, the networked enemy game object is assigned to `PlayerController.currentTarget`. When the player presses X, with a correct target selected, that target is passed through a Command, which runs on the server, to decrement the `health` SyncVar. All clients will be updated with that new value. You can then have a UI on the enemy to show the current value. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars#class-inheritance) Class inheritance ------------------------------------------------------------------------------------------------------------------------------------ SyncVars work with class inheritance. Consider this example: You can attach the Cat component to your cat prefab, and it will synchronize both it's `name` and `color`. > **Warning** Both `Cat` and `Pet` should be in the same assembly. If they are in separate assemblies, make sure not to change `name` from inside `Cat` directly, add a method to `Pet` instead. [PreviousSynchronizationchevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization) [NextSyncVar Hookschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvar-hooks) Last updated 1 year ago * [SyncVar Example](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars#syncvar-example) * [Class inheritance](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars#class-inheritance) Copy public class PlayerController : NetworkBehaviour { public GameObject currentTarget; void Update() { if (isLocalPlayer) if (currentTarget != null && currentTarget.tag == "Enemy") if (Input.GetKeyDown(KeyCode.X)) CmdShoot(currentTarget); } [Command] public void CmdShoot(GameObject enemy) { // Do your own shot validation here because this runs on the server enemy.GetComponent().health -= 5; } } Copy class Pet : NetworkBehaviour { [SyncVar] string name; } class Cat : Pet { [SyncVar] public Color32 color; } --- # NetworkBehaviour Callbacks | Mirror [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#networkbehaviour-callbacks) NetworkBehaviour Callbacks ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- circle-info See also [NetworkBehaviourarrow-up-right](https://storage.googleapis.com/mirror-api-docs/html/db/d21/class_mirror_1_1_network_behaviour.html) in the API Reference. There are a number of events relating to network behaviours that can occur over the course of a normal multiplayer game. These include events such as the host starting up, a player joining, or a player leaving. Each of these possible events has an associated callback that you can implement in your own code to take action when the event occurs. When you create a script which inherits from `NetworkBehaviour`, you can write your own implementation of what should happen when these events occur. To do this, you override the virtual methods on the `NetworkBehaviour` class with your own implementation of what should happen when the given event occurs. This is a full list of virtual methods (callbacks) that you can implement on `NetworkBehaviour`, and where they are called ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#server-only) Server Only * OnStartServer * called when behaviour is spawned on server * OnStopServer * called when behaviour is destroyed or unspawned on server * OnSerialize * called when behaviour is serialize before it is sent to client, when overriding make sure to call `base.OnSerialize` ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#client-only) Client only * OnStartClient * called when behaviour is spawned on client * OnStartAuthority * called when behaviour has authority when it is spawned (eg local player) * called when behaviour is given authority by the sever * OnStartLocalPlayer * called when the behaviour is on the local player object * OnStopAuthority * called when authority is taken from the object (eg local player is replaced but not destroyed) * OnStopClient * called when object is destroyed on client by the `ObjectDestroyMessage` or `ObjectHideMessage` messages [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#example-flows) Example flows --------------------------------------------------------------------------------------------------------------------------------------------- Below is some example call order for different modes > NOTE: `Start` is called by unity before the first frame, while normally this happens after Mirror's callbacks. But if you dont call `NetworkServer.Spawn` the same frame as `instantiate` then start may be called first > Note: `OnRebuildObservers` and `OnSetHostVisibility` is now on `NetworkVisibility` instead of `NetworkBehaviour` ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#server-mode) Server mode When a NetworkServer.Spawn is called (eg when new client connections and a player is created) * `OnStartServer` * `OnRebuildObservers` * `Start` ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#client-mode) Client mode When local player is spawned for client * `OnStartAuthority` * `OnStartClient` * `OnStartLocalPlayer` * `Start` ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#host-mode) Host mode These are only called on the **Player Game Objects** when a client connects: * `OnStartServer` * `OnRebuildObservers` * `OnStartAuthority` * `OnStartClient` * `OnSetHostVisibility` * `OnStartLocalPlayer` * `Start` [PreviousNetworkManager Callbackschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks) [NextNetwork Messageschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/communications/network-messages) Last updated 2 years ago * [NetworkBehaviour Callbacks](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#networkbehaviour-callbacks) * [Server Only](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#server-only) * [Client only](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#client-only) * [Example flows](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#example-flows) * [Server mode](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#server-mode) * [Client mode](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#client-mode) * [Host mode](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkbehaviour-callbacks#host-mode) --- # Data types | Mirror The client and server can pass data to each other via [Remote Actions](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) , [State Synchronization](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization) or via [Network Messages](https://mirror-networking.gitbook.io/docs/manual/guides/communications/network-messages) Mirror supports a number of data types you can use with these, including: * Basic C# types (byte, short, int, long, uint, ushort, ulong, float, double, char, string, etc.) * Built-in Unity math types (Vector3, Quaternion, Rect, Plane, etc.) * Built-in Unity types that are structs under the hood (Color, Sprite, Texture2D, Ray, etc.) * URI * `NetworkIdentity`, `NetworkBehaviour` * **These should not be used in SyncVars or Sync\* Collections or Rpc's because they'll be null on the client if the corresponding object hasn't already been spawned.** * Game object with a `NetworkIdentity` component that have been network spawned * **Not** prefabs! * See important details in [GameObjects](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects) section below. * Structures with any of the above * You must replace the whole struct value, not just change its properties * It's recommended to implement IEquatable to avoid boxing, and to have the struct readonly because modifying one of properties does **not** cause a resync * Classes as long as each field has a supported data type * You must replace the whole class value, not just change its properties * **These will allocate garbage** and will be instantiated new on the receiver every time they're sent. * ScriptableObject as long as each field has a supported data type * **These will allocate garbage** and will be instantiated new on the receiver every time they're sent. * See details in the [ScriptableObjects](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#scriptable-objects) section below. * Arrays of any of the above * Not supported with [Sync\* collections](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization) * ArraySegments of any of the above * Not supported with [Sync\* collections](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization) [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#game-objects) Game Objects ------------------------------------------------------------------------------------------------------------ Game Objects in SyncVars, SyncLists, and SyncDictionaries are fragile in some cases, and should be used with caution. * As long as the game object _already exists_ on both the server and the client, the reference should be fine. When the sync data arrives at the client, the referenced game object may not yet exist on that client, resulting in null values in the sync data. This is because internally Mirror passes the `netId` from the `NetworkIdentity` and tries to look it up on the client's `NetworClient.spawned` dictionary. If the object hasn't been spawned on the client yet, no match will be found. It could be in the same payload, especially for joining clients, but after the sync data from another object. It could also be null because the game object is excluded from a client due to network visibility, e.g. [`Interest Management`](https://mirror-networking.gitbook.io/docs/manual/interest-management) . You may find that it's more robust to sync the `NetworkIdentity.netID` (uint) instead and do your own lookup in `NetworkClient.spawned` to get the object, perhaps in a coroutine: [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#custom-data-types) Custom Data Types ---------------------------------------------------------------------------------------------------------------------- Sometimes you don't want mirror to generate serialization for your own types. For example, instead of serializing quest data, you may want to serialize just the quest id, and the receiver can look up the quest details by the id in a predefined list or database. Sometimes you may want to serialize data which uses a different type not supported by Mirror, such as DateTime. You can add support for any type by adding extension methods to `NetworkWriter` and `NetworkReader`. For example, to add support for `DateTime`, add this somewhere in your project: ...then you can use `DateTime` in your `[Command]` or `SyncList` [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#inheritance-and-polymorphism) Inheritance and Polymorphism -------------------------------------------------------------------------------------------------------------------------------------------- Sometimes you might want to send a polymorphic data type to your commands. Mirror does not serialize the type name to keep messages small and for security reasons, therefore Mirror cannot figure out the type of object it received by looking at the message. > **This code does not work out of the box.** CmdEquip will work if you provide a custom serializer for the `Item` type. For example: [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#scriptable-objects) ScriptableObjects ----------------------------------------------------------------------------------------------------------------------- People often want to send scriptable objects from the client or server. For example, you may have a bunch of swords created as scriptable objects and you want put the equipped sword in a syncvar. This will work fine, Mirror will generate a reader and writer for scriptable objects by calling ScriptableObject.CreateInstance and copy all the data. However the generated reader and writer are not suitable for every occasion. Scriptable objects often reference other assets such as textures, prefabs, or other types that can't be serialized. Scriptable objects are often saved in the in the Resources folder. Scriptable objects sometimes have a large amount of data in them. The generated reader and writers may not work or may be inneficient for these situations. Instead of passing the scriptable object data, you can pass the name and the other side can lookup the same object by name. This way you can have any kind of data in your scriptable object. You can do that by providing a custom reader and writer. Here is an example: [PreviousTime Synchronizationchevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/time-sync) [NextSerializationchevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/serialization) Last updated 2 years ago * [Game Objects](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#game-objects) * [Custom Data Types](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#custom-data-types) * [Inheritance and Polymorphism](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#inheritance-and-polymorphism) * [ScriptableObjects](https://mirror-networking.gitbook.io/docs/manual/guides/data-types#scriptable-objects) Copy public GameObject target; [SyncVar(hook = nameof(OnTargetChanged))] public uint targetID; void OnTargetChanged(uint _, uint newValue) { target = null; if (NetworkClient.spawned.TryGetValue(targetID, out NetworkIdentity identity)) target = identity.gameObject; else StartCoroutine(SetTarget()); } IEnumerator SetTarget() { while (target == null) { yield return null; if (NetworkClient.spawned.TryGetValue(targetID, out NetworkIdentity identity)) target = identity.gameObject; } } Copy public static class DateTimeReaderWriter { public static void WriteDateTime(this NetworkWriter writer, DateTime dateTime) { writer.WriteInt64(dateTime.Ticks); } public static DateTime ReadDateTime(this NetworkReader reader) { return new DateTime(reader.ReadInt64()); } } Copy class Item { public string name; } class Weapon : Item { public int hitPoints; } class Armor : Item { public int hitPoints; public int level; } class Player : NetworkBehaviour { [Command] void CmdEquip(Item item) { // IMPORTANT: this does not work. Mirror will pass you an object of type item // even if you pass a weapon or an armor. if (item is Weapon weapon) { // The item is a weapon, // maybe you need to equip it in the hand } else if (item is Armor armor) { // you might want to equip armor in the body } } [Command] void CmdEquipArmor(Armor armor) { // IMPORTANT: this does not work either, you will receive an armor, but // the armor will not have a valid Item.name, even if you passed an armor with name } } Copy public static class ItemSerializer { const byte WEAPON = 1; const byte ARMOR = 2; public static void WriteItem(this NetworkWriter writer, Item item) { if (item is Weapon weapon) { writer.WriteByte(WEAPON); writer.WriteString(weapon.name); writer.WritePackedInt32(weapon.hitPoints); } else if (item is Armor armor) { writer.WriteByte(ARMOR); writer.WriteString(armor.name); writer.WritePackedInt32(armor.hitPoints); writer.WritePackedInt32(armor.level); } } public static Item ReadItem(this NetworkReader reader) { byte type = reader.ReadByte(); switch(type) { case WEAPON: return new Weapon { name = reader.ReadString(), hitPoints = reader.ReadPackedInt32() }; case ARMOR: return new Armor { name = reader.ReadString(), hitPoints = reader.ReadPackedInt32(), level = reader.ReadPackedInt32() }; default: throw new Exception($"Invalid weapon type {type}"); } } } Copy [CreateAssetMenu(fileName = "New Armor", menuName = "Armor Data")] class Armor : ScriptableObject { public int Hitpoints; public int Weight; public string Description; public Texture2D Icon; // ... } public static class ArmorSerializer { public static void WriteArmor(this NetworkWriter writer, Armor armor) { // no need to serialize the data, just the name of the armor writer.WriteString(armor.name); } public static Armor ReadArmor(this NetworkReader reader) { // load the same armor by name. The data will come from the asset in Resources folder return Resources.Load(reader.ReadString()); } } --- # Deprecated | Mirror The following components have been deprecated and should not be used. Follow the links below for information on what replaced them. * [Network Proximity Checker](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-proximity-checker) * [Network Scene Checker](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-scene-checker) * [Network Match Checker](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-match-checker) * [Network Owner Checker](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-owner-checker) [PreviousSnapshot Interpolationchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation) [NextNetwork Proximity Checkerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-proximity-checker) Last updated 4 years ago --- # SyncVar Hooks | Mirror The hook attribute can be used to specify a function to be called when the SyncVar changes value on the client. * The Hook method must have two parameters of the same type as the SyncVar property. One for the old value, one for the new value. * The Hook is always called after the property value is set. You don't need to set it yourself. * The Hook only fires for changed values, and changing a value in the inspector will not trigger an update. * As of version 11.1.4 (March 2020) and later, hooks can be virtual methods and overriden in a derived class. Below is a simple example of assigning a random color to each player when they're spawned on the server. All clients will see all players in the correct colors, even if they join later. > Note: The signature for hook methods was changed in version 9.0 (Feb 2020) to having 2 parameters (old and new values). If you're on an older version, hook methods just have one parameter (new value). Copy using UnityEngine; using Mirror; public class PlayerController : NetworkBehaviour { [SyncVar(hook = nameof(OnColorChanged))] Color playerColor = Color.black; // Unity makes a clone of the Material every time GetComponent().material is used. // Cache it here and Destroy it in OnDestroy to prevent a memory leak. Material cachedMaterial; public override void OnStartServer() { playerColor = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f); } void OnColorChanged(Color oldColor, Color newColor) { if (cachedMaterial == null) cachedMaterial = GetComponent().material; cachedMaterial.color = newColor; } void OnDestroy() { Destroy(cachedMaterial); } } [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvar-hooks#hook-call-order) Hook call order ------------------------------------------------------------------------------------------------------------------------------------- Hooks are invoked in the order the syncvars are defined in the file. if X, Y, and Z are all set on the server at the same time then the call order will be: 1. X value is set 2. Y value is set 3. Hook1 is called 4. Z value is set 5. Hook2 is called [PreviousSyncVarschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars) [NextSyncEvent (Obsolete)chevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncevent) Last updated 1 year ago Copy public class MyBehaviour : NetworkBehaviour { [SyncVar] int X; [SyncVar(hook = nameof(Hook1))] int Y; [SyncVar(hook = nameof(Hook2))] int Z; } --- # Network Owner Checker | Mirror triangle-exclamation **Network Owner Checker is Obsolete - use** [**Network Team**](https://mirror-networking.gitbook.io/docs/manual/interest-management/team) **component instead.** The Network Owner Checker component controls visibility of networked objects based on owner client. Any object with this component on it will only be visible to the client that has authority ownership of it. This can be used when you want to spawn a network object with client authority and only have it appear for the owner, e.g. an interactive UI or NPC. Since clients can call commands on objects they have authority over, such objects can have Network Behaviors with commands in them that can be called directly by the client. [PreviousNetwork Match Checkerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-match-checker) [NextInterest Managementchevron-right](https://mirror-networking.gitbook.io/docs/manual/interest-management) Last updated 4 years ago --- # Remote Actions | Mirror The network system has ways to perform actions across the network. These type of actions are sometimes called Remote Procedure Calls. There are two types of RPCs in the network system, Commands - which are called from the client and run on the server; and ClientRpc calls - which are called on the server and run on clients. The diagram below shows the directions that remote actions take: ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_qTfPEnSOCoRntjcs%252F-MH_quqZtwY246Y5QMcA%252Fimage.png%3Falt%3Dmedia%26token%3D01f744f7-c7bb-4462-86dc-9844a0ed5cbe&width=768&dpr=3&quality=100&sign=49822d75&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#commands) Commands ----------------------------------------------------------------------------------------------------------------------- Commands are sent from player objects on the client to player objects on the server. For security, Commands can only be sent from YOUR player object by default, so you cannot control the objects of other players. You can bypass the authority check using `[Command(requiresAuthority = false)]`. To make a function into a command, add the \[Command\] custom attribute to it, and optionally add the “Cmd” prefix for naming convention. This function will now be run on the server when it is called on the client. Any parameters of [allowed data type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) will be automatically passed to the server with the command. Commands functions should have the prefix “Cmd” and cannot be static. This is a hint when reading code that calls the command - this function is special and is not invoked locally like a normal function. Be careful of sending commands from the client every frame! This can cause a lot of network traffic. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#bypassing-authority) Bypassing Authority It is possible to invoke commands on non-player objects if any of the following are true: * The object was spawned with client authority * The object has client authority set with `NetworkIdentity.AssignClientAuthority` * the Command has the `requiresAuthority` option set false. * You can include an optional `NetworkConnectionToClient sender = null` parameter in the Command method signature and Mirror will fill in the sending client for you. * Do not try to set a value for this optional parameter...it will be ignored. Commands sent from these objects are run on the server instance of the object, not on the associated player object for the client. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#clientrpc-calls) ClientRpc Calls ------------------------------------------------------------------------------------------------------------------------------------- ClientRpc calls are sent from objects on the server to objects on clients. They can be sent from any server object with a NetworkIdentity that has been spawned. Since the server has authority, then there no security issues with server objects being able to send these calls. To make a function into a ClientRpc call, add the \[ClientRpc\] custom attribute to it, and optionally add the “Rpc” prefix for naming convention. This function will now be run on clients when it is called on the server. Any parameters of [allowed data type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) will automatically be passed to the clients with the ClientRpc call.. ClientRpc functions should have the prefix “Rpc” and cannot be static. This is a hint when reading code that calls the method - this function is special and is not invoked locally like a normal function. When running a game as a host with a local client, ClientRpc calls will be invoked on the local client even though it is in the same process as the server. So the behaviours of local and remote clients are the same for ClientRpc calls. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#excluding-owner) Excluding Owner ClientRpc messages are only sent to observers of an object according to its [Network Visibility](https://mirror-networking.gitbook.io/docs/manual/interest-management) . Player objects are always observers of themselves. In some cases, you may want to exclude the owner client when calling a ClientRpc. This is done with the `includeOwner` option: `[ClientRpc(includeOwner = false)]`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#targetrpc-calls) TargetRpc Calls ------------------------------------------------------------------------------------------------------------------------------------- TargetRpc functions are called by user code on the server, and then invoked on the corresponding client object on the client of the specified `NetworkConnection`. The arguments to the RPC call are serialized across the network, so that the client function is invoked with the same values as the function on the server. These functions should begin with the prefix "Target" for naming convention and cannot be static. **Context Matters:** * If the first parameter of your TargetRpc method is a `NetworkConnection` then that's the connection that will receive the message regardless of context. * If the first parameter is any other type, then the owner client of the object with the script containing your TargetRpc will receive the message. This example shows how a client can use a Command to make a request to the server (`CmdMagic`) by including another Player's `connectionToClient` as one of the parameters of the TargetRpc invoked directly from that Command: [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#arguments-to-remote-actions) Arguments to Remote Actions ------------------------------------------------------------------------------------------------------------------------------------------------------------- The arguments passed to commands and ClientRpc calls are serialized and sent over the network. You can use any [supported mirror type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) . Arguments to remote actions cannot be sub-components of game objects, such as script instances or Transforms. [PreviousCommunicationschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/communications) [NextNetworkManager Callbackschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/communications/networkmanager-callbacks) Last updated 3 years ago * [Commands](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#commands) * [Bypassing Authority](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#bypassing-authority) * [ClientRpc Calls](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#clientrpc-calls) * [Excluding Owner](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#excluding-owner) * [TargetRpc Calls](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#targetrpc-calls) * [Arguments to Remote Actions](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions#arguments-to-remote-actions) Copy public class Player : NetworkBehaviour { // assigned in inspector public GameObject cubePrefab; void Update() { if (!isLocalPlayer) return; if (Input.GetKey(KeyCode.X)) CmdDropCube(); } [Command] void CmdDropCube() { if (cubePrefab != null) { Vector3 spawnPos = transform.position + transform.forward * 2; Quaternion spawnRot = transform.rotation; GameObject cube = Instantiate(cubePrefab, spawnPos, spawnRot); NetworkServer.Spawn(cube); } } } Copy public enum DoorState : byte { Open, Closed, Locked } public class Door : NetworkBehaviour { [SyncVar] public DoorState doorState; [Client] void OnMouseUpAsButton() { CmdSetDoorState(); } [Command(requiresAuthority = false)] public void CmdSetDoorState(NetworkConnectionToClient sender = null) { bool hasDoorKey = sender.identity.GetComponent().hasDoorKey; if (doorState == DoorState.Open) { doorState = hasDoorKey ? DoorState.Locked : DoorState.Closed; return; } if (doorState == DoorState.Locked && hasDoorKey) { doorState = DoorState.Open; return; } if (doorState == DoorState.Closed) doorState = DoorState.Open; } } Copy public class Player : NetworkBehaviour { int health; public void TakeDamage(int amount) { if (!isServer) return; health -= amount; RpcDamage(amount); } [ClientRpc] public void RpcDamage(int amount) { Debug.Log("Took damage:" + amount); } } Copy public class Player : NetworkBehaviour { public int health; [Command] void CmdMagic(GameObject target, int damage) { target.GetComponent().health -= damage; NetworkIdentity opponentIdentity = target.GetComponent(); TargetDoMagic(opponentIdentity.connectionToClient, damage); } [TargetRpc] public void TargetDoMagic(NetworkConnectionToClient target, int damage) { // This will appear on the opponent's client, not the attacking player's Debug.Log($"Magic Damage = {damage}"); } // Heal thyself [Command] public void CmdHealMe() { health += 10; TargetHealed(10); } [TargetRpc] public void TargetHealed(int amount) { // No NetworkConnection parameter, so it goes to owner Debug.Log($"Health increased by {amount}"); } } --- # Network Proximity Checker | Mirror triangle-exclamation **Network Proximity Checker is Obsolete - use** [**Spatial Hash**](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing) **or** [**Distance**](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance) **Interest Management instead.** The Network Proximity Checker component controls the visibility of game objects for network clients, based on proximity to players. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_uK5DEJZtbZjPyVT%252F-MUNa1tYU4VgHzOsvs3w%252Fimage.png%3Falt%3Dmedia%26token%3Dbdfc4826-1bd8-49d0-a5a2-db82d1eab879&width=768&dpr=3&quality=100&sign=e15b4ab&sv=2) * **Vis Range** Define the range that the game object should be visible to observers. * **Vis Update Interval** Define how often (in seconds) the game object should check for observers entering its visible range. * **Check Method** Define which type of physics (2D or 3D) to use for proximity checking. * **Force Hidden** Tick this checkbox to hide this object from all players. With the Network Proximity Checker, a game running on a client doesn’t have information about game objects that are not visible. This has two main benefits: it reduces the amount of data sent across the network, and it makes your game more secure against hacking. This component relies on physics to calculate visibility, so observer game objects must also have a collider component on it. A game object with a Network Proximity Checker component must also have a Network Identity component. When you create a Network Proximity Checker component on a game object, Mirror also creates a Network Identity component on that game object if it does not already have one. Scene objects with a Network Proximity Checker component are disabled when they're out of range, and spawned objects are destroyed when they're out of range. [PreviousDeprecatedchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/deprecated) [NextNetwork Scene Checkerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-scene-checker) Last updated 4 years ago --- # Snapshot Interpolation | Mirror Mirror's `NetworkTransform` component uses [**Snapshot Interpolation**arrow-up-right](https://gafferongames.com/post/snapshot_interpolation/) . circle-info If you are not familiar with the term: **Snapshot Interpolation** interpolates through snapshots, while buffering enough of them to make up for non-ideal networking conditions like latency, packet loss and scramble. When developing the new `NetworkTransform` component, we've had two goals: * **Make it stable**: We needed something that can be used by thousands of projects without _any_ surprises. Major hits already use Mirror in production, so we needed to be extremely careful to get this right. * **Make it reusable**: NetworkTransform is one of many components that need Snapshot Interpolation. Someone might need it for 3D / 2D Rigidbodies, Character Controllers and more. The algorithm however is always the same. In order to achieve both goals, we decided to split the **Snapshot Interpolation** algorithm into a standalone class that can be used by anyone. It's raw C#, completely independent from Mirror & Unity. You can use it in Mirror, or in standalone servers or in different game engines. In short, we wanted to **solve the problem** once and for all, so we have an algorithm that we can use for decades, no matter which engine. circle-info The approach is comparable to **kcp**, which is merely a reliability algorithm that can be used in all languages & engines. For our kcp transport, we simply wrap it in server & client classes and send the results over UDP sockets. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation#simulations-and-tests) Simulations & Tests -------------------------------------------------------------------------------------------------------------------------------------------------------------- **Snapshot Interpolation** is quite difficult to get right. Not only do we operate on two timelines (local & remote), we also have to deal with adverse network conditions like latency spikes, packet loss and scramble. To make matters worse, servers & clients might also be under heavy load and update on significantly different frequencies at times. circle-info To put things into perspective: the Snapshot Interpolation algorithm took us **4 months** of work to get it to work. More than half the time was spent on tests & simulations to guarantee stability. Developing Snapshot Interpolation as a standalone algorithm allows us to **simulate** the different scenarios without even running latency simulation or Mirror: * We can simulate exactly how the snapshot interpolation algorithm behaves if the remote is at t=5, we are at t=3 and we have three snapshots at t=0, 1, 2, while **sampling** through different points of the interpolation. * We can simulate what happens if someone only has two snapshots, reached the end of the interpolation and is still **waiting** for the next one. * We can simulate how the algorithm behaves if a mobile user switches back to the game after a **100s delay**. * We can simulate extremely poor network conditions like 99% **packet loss & scramble**. * We can **catch-up** if the buffer gets too large. * And many more.. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MdvlaaLGmQbPs0lcycc%252F-MdvldG6Yeb9KNOJmbFB%252F2021-07-06_20-23-58%25402x.png%3Falt%3Dmedia%26token%3Df4a72ab6-de3b-4e21-a725-13844aa23153&width=768&dpr=3&quality=100&sign=5c077d4e&sv=2) Snapshot Interpolation Simulations **As result** \_It's only a matter of computing with snapshots & parameters in, result out.\_intended [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation#using-the-algorithm) Using the Algorithm ------------------------------------------------------------------------------------------------------------------------------------------------------------ Please read through our `SnapshotInterpolation.cs` code in Mirror to see the algorithm & helper functions, and then read through `NetworkTransform` as usage example. To summarize, there are a few key aspects: * The **Snapshot** **interface**: your `RigidbodySnapshot`, `CharacterControllerSnapshot` etc. structs have to implement that interface. * The **Time Buffer**, which is a `SortedList` buffer. We offer several helper functions like `InsertIfNewEnough` for convenience. * All of those functions are heavily covered with unit tests. * The **Compute()** algorithm: given a snapshot buffer, time, deltaTime and configuration parameters, it spits out the next interpolated Snapshot (if any). * This function comes with heavy test coverage, in fact it's likely the most tested function in all of Mirror. circle-check Make sure to read the [Snapshot Interpolationarrow-up-right](https://gafferongames.com/post/snapshot_interpolation/) article to understand how it all works, and then look through`SnapshotInterpolation.cs` and `NetworkTransformBase.cs`to see it in action. Even with our provided algorithm, it's still not an easy topic to understand and implement correctly. circle-exclamation Note how`NetworkTransform` sends snapshots **every**`sendInterval`over the **unreliable** channel. Do not send **only if changed**, this would require knowledge about the other end's last received snapshot (either over **reliable**, or with a **notify** algorithm). circle-info Note that NetworkTransform sends **every**`sendInterval`. Bandwidth will be significantly reduced once we implement **Bitpacking** and **Delta Compression** into Mirror. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation#benchmarks-and-results) Benchmarks & Results ---------------------------------------------------------------------------------------------------------------------------------------------------------------- We recommend using Mirror's **LatencySimulationTransport** to try it yourself, for example with our **Benchmark** demo. Even for poor networking conditions, Snapshot Interpolation will perform well as long as the **bufferMultiplier** is high enough. #### [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation#some-test-videos) Some test videos: * NetworkTransform [old vs. new comparisonarrow-up-right](https://youtu.be/z2JpT_qLmzk) on Youtube (secret project). * See the original [Pull Requestarrow-up-right](https://github.com/vis2k/Mirror/pull/2791) progress videos. You can see how latency, loss & scramble are gradually solved with every added feature. * JesusLovsYooh old vs. new NetworkTransform _(watch the left build, OG NT is the old one and NT 2k is the new one)_ Skip halfway through to see new NT under bad network conditions. [PreviousNetwork Transformchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-transform) [NextDeprecatedchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/deprecated) Last updated 1 year ago * [Simulations & Tests](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation#simulations-and-tests) * [Using the Algorithm](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation#using-the-algorithm) * [Benchmarks & Results](https://mirror-networking.gitbook.io/docs/manual/components/network-transform/snapshot-interpolation#benchmarks-and-results) --- # Network Authenticators | Mirror When you have a multiplayer game, often you need to store information about your player for later games, keep game stats or communicate with your friends. For all these use cases, you often need a way to uniquely identify a user. Being able to tell users apart is called authentication. There are several methods available, some examples include: * Ask the user for username and password * Use a third party OAuth2 or OpenID identity provider, such as Facebook, Twitter, Google * Use a third party service such as PlayFab, GameLift or Steam * Use the device id, very popular method in mobile * Use Google Play in Android * Use Game Center in IOS * Use a web service in your website [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#encryption-notice) Encryption Notice -------------------------------------------------------------------------------------------------------------------------------------- Few of the available transports support encryption, so if you want to do authentication through Mirror, we highly recommend you use a transport that does, e.g. [SimpleWebSocket arrow-up-right](https://mirror-networking.gitbook.io/docs/transports/websockets-transport) Transport, or carry out your exchange of sensitive data using UnityWebRequest with a service over HTTPS. This can be done inside an Authenticator, or before calling `StartClient`. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#offline-online-scenes) Offline / Online Scenes ------------------------------------------------------------------------------------------------------------------------------------------------ Authentication takes place in the Offline scene, and messages are exchanged with the game server in a pre-connect phase, so client stays in the Offline scene until authentication completes. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#persisting-data) Persisting Data ---------------------------------------------------------------------------------------------------------------------------------- `NetworkConnection` has an `**authenticationData**` property of type `Object` that can be set to pretty much anything you need, such as account id's, tokens, character selection, etc., including a struct of data, on the server and/or client during the authentication process. That data is available everywhere else in Mirror where you have the client's `NetworkConnection`...just cast it back to whatever type you put into it. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#basic-authenticator) Built-in Authenticators ---------------------------------------------------------------------------------------------------------------------------------------------- * [Basic Authenticator](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators/basic-authenticator) Mirror includes a Basic Authenticator in the Mirror / Authenticators folder which just uses a simple username and password. * [Device Authenticator](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators/device-authenticator) Uses `SystemInfo.deviceUniqueIdentifier` on supported platforms, and GUID in PlayerPrefs as a fallback for platforms that don't. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#custom-authenticators) Custom Authenticators ---------------------------------------------------------------------------------------------------------------------------------------------- Authenticators are derived from an `Authenticator` abstract class that allows you to implement any authentication scheme you need. From the Assets menu, click Create > Mirror > Network Authenticator to make your own custom Authenticator from our [Script Templates](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) , and just fill in the messages and validation code to suit your needs. When a client is successfully authenticated, call `ServerAccept(conn)` on the server and `ClientAccept()` on the client. Mirror is listening for these events to proceed with the connection sequence. Subscribe to `OnServerAuthenticated` and `OnClientAuthenticated` events if you wish to perform additional steps after authentication. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#message-registration) Message Registration -------------------------------------------------------------------------------------------------------------------------------------------- By default all messages registered to `NetworkServer` and `NetworkClient` require authentication unless explicitly indicated otherwise. To register messages to bypass authentication, you need to specify `false` for a bool parameter to the `RegisterMessage` method: Certain internal messages already have been set to bypass authentication: * Server * `NetworkPingMessage` * Client * `SceneMessage` * `NetworkPongMessage` [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#tips) Tips ------------------------------------------------------------------------------------------------------------ * Register handlers for messages in `OnStartServer` and `OnStartClient`. They're called from StartServer/StartHost, and StartClient, respectively. * Send a message to the client if authentication fails, especially if there's some issue they can resolve. * Call the `Disconnect()` method of the `NetworkConnection` on the server and client when authentication fails. If you want to give the user a few tries to get their credentials right, you certainly can, but Mirror will not do the disconnect for you. * Remember to put a small delay on the Disconnect call on the server if you send a failure message so that it has a chance to be delivered before the connection is dropped. At a minimum, yield one frame. Now that you have the foundation of a custom Authenticator component, the rest is up to you. You can exchange any number of custom messages between the server and client as necessary to complete your authentication process before approving the client. Authentication can also be extended to character selection and customization, just by crafting additional messages and exchanging them with the client before completing the authentication process. This means this process takes place before the client player actually enters the game or changes to the Online scene. If you write a good authenticator, consider sharing it with other users or donating it to the Mirror project. [PreviousNetwork Animatorchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-animator) [NextBasic Authenticatorchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators/basic-authenticator) Last updated 3 years ago * [Encryption Notice](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#encryption-notice) * [Offline / Online Scenes](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#offline-online-scenes) * [Persisting Data](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#persisting-data) * [Built-in Authenticators](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#basic-authenticator) * [Custom Authenticators](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#custom-authenticators) * [Message Registration](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#message-registration) * [Tips](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators#tips) Copy NetworkServer.RegisterHandler(OnAuthRequestMessage, false); --- # Network Match Checker | Mirror triangle-exclamation **Network Match Checker is Obsolete - use** [**Network Match**](https://mirror-networking.gitbook.io/docs/manual/interest-management/match) **component instead.** The Network Match Checker component controls visibility of networked objects based on match id. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUN_Q_0G6Qds1Vt4wav%252F-MUN_XfH0FPq60gcYWUH%252Fimage.png%3Falt%3Dmedia%26token%3D776d39d5-7fbd-4fe9-9a3b-65866109b861&width=768&dpr=3&quality=100&sign=3fca8b2f&sv=2) Any object with this component on it will only be visible to other objects in the same match. This would be used to isolate players to their respective matches within a single game server instance. When you create a match, generate and store, in a List for example, a new match id with `System.Guid.NewGuid();` and assign the same match id to the Network Match Checker via `GetComponent().matchId`. Mirror's built-in Observers system will isolate SyncVar's and ClientRpc's on networked objects to only send updates to clients with the same match id. [PreviousNetwork Scene Checkerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-scene-checker) [NextNetwork Owner Checkerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-owner-checker) Last updated 4 years ago --- # Custom Character Spawning | Mirror Many games need character customization. You may want to pick the color of the hair, eyes, skin, height, race, etc. By default Mirror will instantiate the player for you. While that is convenient, it might prevent you from customizing it. Mirror provides the option of overriding player creation and customize it. 1. Create a class that extends `NetworkManager` if you have not done so. For example: Copy public class MMONetworkManager : NetworkManager { ... } and use it as your Network manager. 1. Open your Network Manager in the inspector and disable the "Auto Create Player" Boolean. 2. Create a message that describes your player. For example: Copy public struct CreateMMOCharacterMessage : NetworkMessage { public Race race; public string name; public Color hairColor; public Color eyeColor; } public enum Race { None, Elvish, Dwarvish, Human } 1. Create your player prefabs (as many as you need) and add them to the "Register Spawnable Prefabs" in your Network Manager, or add a single prefab to the player prefab field in the inspector. 2. Send your message and register a player: [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning#ready-state) Ready State ------------------------------------------------------------------------------------------------------------------------------------- In addition to players, client connections also have a “ready” state. The host sends clients that are ready information about spawned game objects and state synchronization updates; clients which are not ready are not sent these updates. When a client initially connects to a server, it is not ready. While in this non-ready state, the client can do things that don’t require real-time interactions with the game state on the server, such as loading Scenes, allowing the player to choose an avatar, or fill in log-in boxes. Once a client has completed all its pre-game work, and all its Assets are loaded, it can call `NetworkClient.Ready` to enter the “ready” state. The simple example above demonstrates implementation of ready states; because adding a player with `NetworkServer.AddPlayerForConnection` also puts the client into the ready state if it is not already in that state. Clients can send and receive network messages without being ready, which also means they can do so without having an active player game object. So a client at a menu or selection screen can connect to the game and interact with it, even though they have no player game object. See documentation on [Network Messages](https://mirror-networking.gitbook.io/docs/manual/guides/communications/network-messages) for more details about sending messages without using commands and RPC calls. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning#switching-players) Switching Players ------------------------------------------------------------------------------------------------------------------------------------------------- To replace the player game object for a connection, use `NetworkServer.ReplacePlayerForConnection`. This is useful for restricting the commands that players can issue at certain times, such as in a pregame room screen. This function takes the same arguments as `AddPlayerForConnection`, but allows there to already be a player for that connection. The old player game object does not have to be destroyed. The `NetworkRoomManager` uses this technique to switch from the `NetworkRoomPlayer` game object to a game play player game object when all the players in the room are ready. You can also use `ReplacePlayerForConnection` to respawn a player or change the object that represents the player. In some cases it is better to just disable a game object and reset its game attributes on respawn. The following code sample demonstrates how to actually replace the player game object with a new game object: If the player game object for a connection is destroyed, then that client cannot execute Commands. They can, however, still send network messages. To use `ReplacePlayerForConnection` you must have the `NetworkConnection` game object for the player’s client to establish the relationship between the game object and the client. This is usually the property `connectionToClient` on the `NetworkBehaviour` class, but if the old player has already been destroyed, then that might not be readily available. To find the connection, there are some lists available. If using the `NetworkRoomManager`, then the room players are available in `roomSlots`. The `NetworkServer` also has lists of `connections`. [PreviousPlayer Game Objectschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/player-gameobjects) [NextCustom Spawn Functionschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-spawnfunctions) Last updated 3 years ago * [Ready State](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning#ready-state) * [Switching Players](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning#switching-players) Copy public class MMONetworkManager : NetworkManager { public override void OnStartServer() { base.OnStartServer(); NetworkServer.RegisterHandler(OnCreateCharacter); } public override void OnClientConnect() { base.OnClientConnect(); // you can send the message here, or wherever else you want CreateMMOCharacterMessage characterMessage = new CreateMMOCharacterMessage { race = Race.Elvish, name = "Joe Gaba Gaba", hairColor = Color.red, eyeColor = Color.green }; NetworkClient.Send(characterMessage); } void OnCreateCharacter(NetworkConnectionToClient conn, CreateMMOCharacterMessage message) { // playerPrefab is the one assigned in the inspector in Network // Manager but you can use different prefabs per race for example GameObject gameobject = Instantiate(playerPrefab); // Apply data from the message however appropriate for your game // Typically Player would be a component you write with syncvars or properties Player player = gameobject.GetComponent(); player.hairColor = message.hairColor; player.eyeColor = message.eyeColor; player.name = message.name; player.race = message.race; // call this to use this gameobject as the primary controller NetworkServer.AddPlayerForConnection(conn, gameobject); } } Copy public class MyNetworkManager : NetworkManager { public void ReplacePlayer(NetworkConnectionToClient conn, GameObject newPrefab) { // Cache a reference to the current player object GameObject oldPlayer = conn.identity.gameObject; // Instantiate the new player object and broadcast to clients // Include true for keepAuthority paramater to prevent ownership change NetworkServer.ReplacePlayerForConnection(conn, Instantiate(newPrefab), true); // Remove the previous player object that's now been replaced // Delay is required to allow replacement to complete. Destroy(oldPlayer, 0.1f); } } --- # Network Scene Checker | Mirror triangle-exclamation **Network Scene Checker is Obsolete - use** [**Scene Interest Management**](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene) **instead.** The Network Scene Checker component controls the visibility of game objects for network clients, based on which scene they're in. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNaZifb5M24bkYKDZD%252F-MUNap7oJi3lk91pOop3%252Fimage.png%3Falt%3Dmedia%26token%3D7d5d3e1c-6314-4c1f-bcdb-c686371ec5b8&width=768&dpr=3&quality=100&sign=c55bc62&sv=2) * **Force Hidden** Tick this checkbox to hide this object from all players. With the Network Scene Checker, a game running on a client doesn’t have information about game objects that are not visible. This has two main benefits: it reduces the amount of data sent across the network, and it makes your game more secure against hacking. This component would typically be used when the server has several subscenes loaded and needs to isolate networked objects to the subscene they're in. A game object with a Network Scene Checker component must also have a Network Identity component. When you create a Network Scene Checker component on a game object, Mirror also creates a Network Identity component on that game object if it does not already have one. Scene objects with a Network Scene Checker component are disabled when they're not in the same scene, and spawned objects are destroyed when they're not in the same scene. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-scene-checker#use-with-additive-scenes) Use with Additive Scenes -------------------------------------------------------------------------------------------------------------------------------------------------------------- In Mirror, the Server and connected Clients are always on the same main scene, however the server and clients can have various combinations of smaller subscenes loaded additively. The server may load all subscenes at start, or it may dynamically load and unload subscenes where players or other activity is going on as needed. All player objects are always first spawned in the main scene, which may or may not have visual content, networked objects, etc. With this component attached to all networked objects, whenever the player object is moved to a subscene (from the main or from another subscene), the observers lists for objects in both the new scene and the prior scene are updated accordingly. Loading the subscene(s) on the server is through the normal process with `SceneManager`: Next, you will send a `SceneMessage` to the client telling it to load a subscene additively: Then, on the server only, you just move the player object to the subscene: Optionally you can send another `SceneMessage` to the client with `SceneOperation.UnloadAdditive` to remove any previous additive scene the client no longer needs. This would apply to a game that has levels after a level change. A short delay may be necessary before removal to allow the client to get fully synced. Depending on the complexity of your game, you may find it helpful when switching a player between subscenes to move the player object to the main scene first, yield 100 ms, re-position it, and finally move it to the new subscene. [PreviousNetwork Proximity Checkerchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-proximity-checker) [NextNetwork Match Checkerchevron-right](https://mirror-networking.gitbook.io/docs/manual/components/deprecated/network-match-checker) Last updated 4 years ago Copy SceneManager.LoadSceneAsync(subScene, LoadSceneMode.Additive); Copy SceneMessage msg = new SceneMessage { sceneName = subScene, sceneOperation = SceneOperation.LoadAdditive }; connectionToClient.Send(msg); Copy // Position the player object in world space first // This assumes it has a NetworkTransform component that will update clients player.transform.position = new Vector3(100, 1, 100); // Then move the player object to the subscene SceneManager.MoveGameObjectToScene(player, subScene); --- # SyncSortedSet | Mirror `SyncSortedSet` are sets similar to C# [SortedSetarrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.sortedset-1) that synchronize their contents from the server to the clients. Unlike SyncHashSets, all elements in a SyncSortedSet are sorted when they are inserted. Please note this has some performance implications. A SyncSortedSet can contain any [supported mirror type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncsortedset#usage) Usage ----------------------------------------------------------------------------------------------------------------- circle-info SyncSortedSet must be declared **readonly** and initialized in the constructor. circle-exclamation Note that by the time you wire up the Action handlers, the sorted set will already be initialized, so they will not get invoked for the initial data, only updates. Copy using UnityEngine; using Mirror; public class SyncSortedSetExample : NetworkBehaviour { public readonly SyncSortedSet namesSortedSet = new SyncSortedSet(); public override void OnStartClient() { // Add handlers for SyncSortedSet Actions namesSortedSet.OnAdd += OnItemAdded; namesSortedSet.OnRemove += OnItemRemoved; namesSortedSet.OnClear += OnSortedSetCleared; // OnChange is a catch-all event that is called for any change // to the SortedSet. It is called after the specific events above. // Strongly recommended to use the specific events above instead! namesSortedSet.OnChange += OnSortedSetChanged; // SortedSet is populated before handlers are wired up so we // need to manually invoke OnAdd for each element. foreach (string value in namesSortedSet) namesSortedSet.OnAdd.Invoke(value); } public override void OnStopClient() { // Remove handlers when client stops namesSortedSet.OnAdd -= OnItemAdded; namesSortedSet.OnRemove -= OnItemRemoved; namesSortedSet.OnClear -= OnSortedSetCleared; namesSortedSet.OnChange -= OnSortedSetChanged; } void OnItemAdded(string value) { Debug.Log($"Element added {value}"); } void OnItemRemoved(string value) { Debug.Log($"Element removed {value}"); } void OnSortedSetCleared() { // OnSortedSetCleared is called before the SortedSet is actually cleared // so we can iterate the SortedSet to get the elements if needed. foreach (string value in namesSortedSet) Debug.Log($"Element cleared {value}"); } // OnSortedSetChanged is a catch-all event that is called for any change // to the SortedSet. It is called after the specific events above. // // NOTE: It's strongly recommended to use the specific events above instead! // // For OP_ADD, the value param is the NEW entry. // For OP_REMOVE, the value param is the OLD entry. // For OP_CLEAR, the value param is null / default. void OnSortedSetChanged(SyncSortedSet.Operation op, string value) { switch (op) { case SyncSortedSet.Operation.OP_ADD: // value is the new entry Debug.Log($"Element added {value}"); break; case SyncSortedSet.Operation.OP_REMOVE: // value is the old entry Debug.Log($"Element removed {value}"); break; case SyncSortedSet.Operation.OP_CLEAR: // value is null / default // we can iterate the SortedSet to get the elements if needed. foreach (string name in namesSortedSet) Debug.Log($"Element cleared {name}"); break; } } } [PreviousSyncHashSetchevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synchashset) [NextCommunicationschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/communications) Last updated 1 year ago --- # SyncHashSet | Mirror `SyncHashSet` are sets similar to C# [HashSetarrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1) that synchronize their contents from the server to the clients. A SyncHashSet can contain any [supported mirror type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synchashset#usage) Usage --------------------------------------------------------------------------------------------------------------- circle-info SyncHashSet must be declared **readonly** and initialized in the constructor. circle-exclamation Note that by the time you wire up the Action handlers, the hashset will already be initialized, so they will not get invoked for the initial data, only updates. Copy using UnityEngine; using Mirror; public class SyncHashSetExample : NetworkBehaviour { public readonly SyncHashSet namesHashSet = new SyncHashSet(); public override void OnStartClient() { // Add handlers for SyncHashSet Actions namesHashSet.OnAdd += OnItemAdded; namesHashSet.OnRemove += OnItemRemoved; namesHashSet.OnClear += OnHashSetCleared; // OnChange is a catch-all event that is called for any change // to the hashset. It is called after the specific events above. // Strongly recommended to use the specific events above instead! namesHashSet.OnChange += OnHashSetChanged; // Hashset is populated before handlers are wired up so we // need to manually invoke OnAdd for each element. foreach (string value in namesHashSet) namesHashSet.OnAdd.Invoke(value); } public override void OnStopClient() { // Remove handlers when client stops namesHashSet.OnAdd -= OnItemAdded; namesHashSet.OnRemove -= OnItemRemoved; namesHashSet.OnClear -= OnHashSetCleared; namesHashSet.OnChange -= OnHashSetChanged; } void OnItemAdded(string value) { Debug.Log($"Element added {value}"); } void OnItemRemoved(string value) { Debug.Log($"Element removed {value}"); } void OnHashSetCleared() { // OnHashSetCleared is called before the hashset is actually cleared // so we can iterate the hashset to get the elements if needed. foreach (string value in namesHashSet) Debug.Log($"Element cleared {value}"); } // OnHashSetChanged is a catch-all event that is called for any change // to the hashset. It is called after the specific events above. // // NOTE: It's strongly recommended to use the specific events above instead! // // For OP_ADD, the value param is the NEW entry. // For OP_REMOVE, the value param is the OLD entry. // For OP_CLEAR, the value param is null / default. void OnHashSetChanged(SyncHashSet.Operation op, string value) { switch (op) { case SyncHashSet.Operation.OP_ADD: // value is the new entry Debug.Log($"Element added {value}"); break; case SyncHashSet.Operation.OP_REMOVE: // value is the old entry Debug.Log($"Element removed {value}"); break; case SyncHashSet.Operation.OP_CLEAR: // value is null / default // we can iterate the hashset to get the elements if needed. foreach (string name in namesHashSet) Debug.Log($"Element cleared {name}"); break; } } } [PreviousSyncDictionarychevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary) [NextSyncSortedSetchevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncsortedset) Last updated 1 year ago --- # Custom Spawn Functions | Mirror You can use spawn handler functions to customize the default behavior when creating spawned game objects on the client. Spawn handler functions ensure you have full control of how you spawn the game object, as well as how you destroy it. Use `NetworkClient.RegisterSpawnHandler` or `NetworkClient.RegisterPrefab` to register functions to spawn and destroy client game objects. The server creates game objects directly, and then spawns them on the clients through this functionality. This functions takes either the asset ID or a prefab and two function delegates: one to handle creating game objects on the client, and one to handle destroying game objects on the client. The asset ID can be a dynamic one, or just the asset ID found on the prefab game object you want to spawn. The Spawn / Unspawn delegates will look something like this: **Spawn Handler** Copy GameObject SpawnDelegate(Vector3 position, uint assetId) { // do stuff here } or Copy GameObject SpawnDelegate(SpawnMessage msg) { // do stuff here } **UnSpawn Handler** Copy void UnSpawnDelegate(GameObject spawned) { // do stuff here } When a prefab is saved its `assetId` field will be automatically set. If you want to create prefabs at runtime you will have to generate a new GUID. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-spawnfunctions#generate-prefab-at-runtime) **Generate Prefab At Runtime** **Use existing prefab** **Spawn on Server** The spawn functions themselves are implemented with the delegate signature. Here is the coin spawner. The `SpawnCreature` would look the same, but have different spawn logic: When using custom spawn functions, it is sometimes useful to be able to unspawn game objects without destroying them. This can be done by calling `NetworkServer.UnSpawn`. This causes the object to be `Reset` on the server and sends a `ObjectDestroyMessage` to clients. The `ObjectDestroyMessage` will cause the custom unspawn function to be called on the clients. If there is no unspawn function the object will instead be `Destroy` Note that on the host, game objects are not spawned for the local client, because they already exist on the server. This also means that no spawn or unspawn handler functions are called. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-spawnfunctions#pooling-game-objects) Pooling Game Objects To avoid Instantiating & Destroying heavily used GameObjects, it can be useful to pool them instead. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FYX5HH3syzC9c9vEljR5e%252F2022-04-04_20-21-49%25402x.png%3Falt%3Dmedia%26token%3D35e3d8a1-d7d5-4b19-88b4-43934624e30c&width=768&dpr=3&quality=100&sign=64d47302&sv=2) Here is an example of how you might set up a simple game object pooling system with custom spawn handlers. Spawning and unspawning then puts game objects in or out of the pool. To use this pool, add the `PrefabPool` component (code above) to the NetworkManager. Next, drag a prefab you want to spawn multiple times to the Prefab field. circle-exclamation Make sure to remove the prefab from NetworkManager's spawnable prefabs list. There should only be one way to spawn it. Otherwise Mirror show a warning. We can modify our Tanks example to showcase the Pooling system. Open Tank.cs and find the CmdFire function: Instead of Instantiating, grab a Prefab from the Pool: Projectile.cs currently destroys itself via GameObject.Destroy: Instead, we simply Unspawn it and return it to the pool: Press Play and fire some projectiles. Notice how nothing is instantiated. Instead, NetworkManager has a pool of children which are disabled until they are needed. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MGmQrf2z6FL0ZpExPAn%252Fuploads%252FhWq9FGY2fhZZMOeN44Sr%252F2022-04-04_20-22-58%25402x.png%3Falt%3Dmedia%26token%3D94170634-9b3c-4241-9e99-872164be473f&width=768&dpr=3&quality=100&sign=773784b5&sv=2) [PreviousCustom Character Spawningchevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning) [NextScene GameObjectschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/scene-gameobjects) Last updated 1 year ago * [Generate Prefab At Runtime](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-spawnfunctions#generate-prefab-at-runtime) * [Pooling Game Objects](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-spawnfunctions#pooling-game-objects) Copy // generate a new unique assetId System.Guid creatureAssetGuid = System.Guid.NewGuid(); uint creatureAssetId = NetworkIdentity.AssetGuidToUint(creatureAssetGuid); // register handlers for the new assetId NetworkClient.RegisterSpawnHandler(creatureAssetId, SpawnCreature, UnSpawnCreature); Copy // register prefab you'd like to custom spawn and pass in handlers NetworkClient.RegisterPrefab(coinAssetId, SpawnCoin, UnSpawnCoin); Copy // spawn a coin - SpawnCoin is called on client NetworkServer.Spawn(gameObject, coinAssetId); Copy public GameObject SpawnCoin(SpawnMessage msg) { return Instantiate(m_CoinPrefab, msg.position, msg.rotation); } public void UnSpawnCoin(GameObject spawned) { Destroy(spawned); } Copy using UnityEngine; namespace Mirror.Examples { public class PrefabPool : MonoBehaviour { // singleton for easier access from other scripts public static PrefabPool singleton; [Header("Settings")] public GameObject prefab; [Header("Debug")] public int currentCount; public Pool pool; void Start() { InitializePool(); singleton = this; NetworkClient.RegisterPrefab(prefab, SpawnHandler, UnspawnHandler); } // used by NetworkClient.RegisterPrefab GameObject SpawnHandler(SpawnMessage msg) => Get(msg.position, msg.rotation); // used by NetworkClient.RegisterPrefab void UnspawnHandler(GameObject spawned) => Return(spawned); void OnDestroy() { NetworkClient.UnregisterPrefab(prefab); } void InitializePool() { // create pool with generator function pool = new Pool(CreateNew, 5); } GameObject CreateNew() { // use this object as parent so that objects dont crowd hierarchy GameObject next = Instantiate(prefab, transform); next.name = $"{prefab.name}_pooled_{currentCount}"; next.SetActive(false); currentCount++; return next; } // Used to take Object from Pool. // Should be used on server to get the next Object // Used on client by NetworkClient to spawn objects public GameObject Get(Vector3 position, Quaternion rotation) { GameObject next = pool.Get(); // set position/rotation and set active next.transform.position = position; next.transform.rotation = rotation; next.SetActive(true); return next; } // Used to put object back into pool so they can b // Should be used on server after unspawning an object // Used on client by NetworkClient to unspawn objects public void Return(GameObject spawned) { // disable object spawned.SetActive(false); // add back to pool pool.Return(spawned); } } } Copy [Command] void CmdFire() { GameObject projectile = Instantiate(projectilePrefab, projectileMount.position, projectileMount.rotation); NetworkServer.Spawn(projectile); RpcOnFire(); } Copy [Command] void CmdFire() { GameObject projectile = PrefabPool.singleton.Get(projectileMount.position, projectileMount.rotation); NetworkServer.Spawn(projectile); RpcOnFire(); } Copy [Server] void DestroySelf() { NetworkServer.Destroy(gameObject); } Copy [Server] void DestroySelf() { // return to prefab pool NetworkServer.UnSpawn(gameObject); PrefabPool.singleton.Return(gameObject); } --- # Network Behaviour | Mirror circle-info See also [NetworkBehaviourarrow-up-right](https://storage.googleapis.com/mirror-api-docs/html/db/d21/class_mirror_1_1_network_behaviour.html) in the API Reference. Network Behaviour scripts work with game objects that have a Network Identity component. These scripts can perform high-level API functions such as Commands, ClientRpc's, and SyncVars. triangle-exclamation Do not put objects in `DontDestroyOnLoad` (DDOL) in Awake. You can do that in Start instead. With the server-authoritative system of Mirror, the server must use the `NetworkServer.Spawn` function to spawn game objects with Network Identity components. Spawning them this way assigns them a `netId` and creates them on clients connected to the server. **Note:** This is not a component that you can add to a game object directly. Instead, you must create a script which inherits from `NetworkBehaviour` (instead of the default `MonoBehaviour`), then you can add your script as a component to a game object. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#properties) Properties ------------------------------------------------------------------------------------------------------------------ * **isServer** Returns true in server context if this game object has been spawned. * **isClient** Returns true in client context if this game object has been spawned by the server. * **isLocalPlayer** Returns true on the client if this game object represents the player created for this client. * **isOwned** (formerly `hasAuthority`) Returns true on the client if this client has [authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority) over this game object. It is meaningless in server context. * **netId** The unique network ID of this game object. The server assigns this at run time. It is unique for all game objects on the network. * **netIdentity** Returns the Network Identity of this object * **connectionToServer** The Network Connection associated with the Network Identity component attached to this game object. This is only valid for the **local player object** on the client, and is null for other player objects that may exist on the client. * **connectionToClient** The Network Connection associated with the Network Identity component attached to this game object. This is valid for game objects on the server that have been assigned to a specific client, e.g. player objects, pets, henchmen, or other objects a single client "owns". Network Behaviour scripts have the following features: * Synchronized variables * Network callbacks * Server and client functions * Sending commands * Client RPC calls * Networked events ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MH_qTfPEnSOCoRntjcs%252F-MH_quqZtwY246Y5QMcA%252Fimage.png%3Falt%3Dmedia%26token%3D01f744f7-c7bb-4462-86dc-9844a0ed5cbe&width=768&dpr=3&quality=100&sign=49822d75&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#network-callbacks) Network Callbacks -------------------------------------------------------------------------------------------------------------------------------- There are built-in callback functions which are invoked on Network Behaviour scripts for various network events. These are virtual functions on the base class, so you can override them in your own code like this: The built-in callbacks are: * **OnStartServer** called on server when a game object spawns on the server, or when the server is started for game objects in the Scene * **OnStopServer** called on server when a game object is destroyed on the server, or when the server is stopped for game objects in the Scene * **OnStartClient** called on clients when the game object spawns on the client, or when the client connects to a server for game objects in the Scene * **OnStopClient** called on clients when the server destroys the game object * **OnStartLocalPlayer** called on clients after `OnStartClient` for the player game object on the local client * **OnStopLocalPlayer** called on clients before `OnStopClient` for the player game object on the local client * **OnStartAuthority** called on owner client when assigned authority by the server. `isOwned` will be true for such objects in client context. * **OnStopAuthority** called on owner client when authority is removed by the server. Note that in a peer-hosted setup, when one of the clients is acting as both host and client, both `OnStartServer` and `OnStartClient` are called on the same game object. Both these functions are useful for actions that are specific to either the client or server, such as suppressing effects on a server, or setting up client-side events. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#server-and-client-functions) Server and Client Attributes ----------------------------------------------------------------------------------------------------------------------------------------------------- You can tag methods in Monobehaviour and Network Behaviour scripts with custom attributes to designate them as server-only or client-only functions. `[Server]` and `[ServerCallback]` return immediately if the client is not active. Likewise, `[Client]` and `[ClientCallback]` return immediately if the server is not active. The `[Server]` and `[Client]` attributes do not generate compile time errors, but they do emit a warning log message if called in the wrong context. The `ServerCallback` and `ClientCallback` attributes act the same as above but do not cause a warning to be generated. For more information, see [Attributes](https://mirror-networking.gitbook.io/docs/manual/guides/attributes) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#commands) Commands -------------------------------------------------------------------------------------------------------------- To execute code on the server, you must use Commands. The high-level API is a server-authoritative system, so Commands are the only way for a client to trigger some code on the server. Typically only player objects can have Commands, however they may also exist on other networked objects, and may be called by a client that has authority assigned for that object, or by any client where [bypassing authority](https://mirror-networking.gitbook.io/docs/manual/guides/communications/remote-actions) has been specifically indicated. When a client player game object sends a command, that command runs on the corresponding player game object on the server. This routing happens automatically, so it is impossible for a client to send a command for a different player. To define a Command in your code, you must decorate a method with the \[Command\] attribute. While not required, it is strongly suggested to prefix method names with `Cmd` so it's easier to recognize in your calling code what will be happening. Commands are called just by invoking the method normally on the client. Instead of the method running on the client, it is automatically invoked on the corresponding player game object on the server. Commands are type-safe, have built-in security and routing to the player, and use an efficient serialization mechanism for the arguments to make calling them fast. See [Communications](https://mirror-networking.gitbook.io/docs/manual/guides/communications) and related sections for more information. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#client-rpc-calls) Client RPC Calls ------------------------------------------------------------------------------------------------------------------------------ Client RPC calls are a way for server game objects to make things happen on client game objects. Client RPC calls are not restricted to player game objects, and may be called on any game object with a Network Identity component. To define a Client RPC call in your code, you must decorate the method with `[ClientRpc]`. While not required, it is strongly suggested to prefix method names with `Rpc` so it's easier to recognize in your calling code what will be happening. See [Communications](https://mirror-networking.gitbook.io/docs/manual/guides/communications) and related sections for more information. [hashtag](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#networked-events-obsolete) Networked Events (Obsolete) -------------------------------------------------------------------------------------------------------------------------------------------------- > **IMPORTANT** SyncEvents have been removed in version 18.0.0, see this [Issuearrow-up-right](https://github.com/vis2k/Mirror/pull/2178) > for more information Networked events are like Client RPC calls, but instead of calling a function on the game object, they trigger Events instead. This allows you to write scripts which can register for a callback when an event is triggered. To define a Networked event in your code, you must write a function which both: * Has a name that begins with `Event` * Has the `SyncEvent` attribute You can use events to build powerful networked game systems that can be extended by other scripts. This example shows how an effect script on the client can respond to events generated by a combat script on the server. SyncEvent is the base class that Commands and ClientRpc calls are derived from. You can use the SyncEvent attribute on your own functions to make your own event-driven networked game play code. Using SyncEvent, you can extend Mirror’s Multiplayer features to better fit your own programming patterns. See [SyncEvents](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncevent) for more details. [PreviousDevice Authenticatorchevron-left](https://mirror-networking.gitbook.io/docs/manual/components/network-authenticators/device-authenticator) [NextNetwork Discoverychevron-right](https://mirror-networking.gitbook.io/docs/manual/components/network-discovery) Last updated 2 years ago * [Properties](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#properties) * [Network Callbacks](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#network-callbacks) * [Server and Client Attributes](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#server-and-client-functions) * [Commands](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#commands) * [Client RPC Calls](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#client-rpc-calls) * [Networked Events (Obsolete)](https://mirror-networking.gitbook.io/docs/manual/components/networkbehaviour#networked-events-obsolete) Copy public class SpaceShip : NetworkBehaviour { public override void OnStartServer() { // disable client stuff } public override void OnStartClient() { // register client events, enable effects } } --- # Synchronization | Mirror State synchronization refers to the synchronization of values such as integers, floating point numbers, strings and boolean values belonging to scripts. State synchronization is done from the Server to remote clients. The local client does not have data serialized to it. It does not need it, because it shares the Scene with the server. However, SyncVar hooks are called on local clients. Data is not synchronized in the opposite direction - from remote clients to the server. To do this, you need to use Commands. * [SyncVars](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars) SyncVars are variables of scripts that inherit from NetworkBehaviour, which are synchronized from the server to clients. * [SyncEvents (Obsolete)](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncevent) SyncEvents are networked events like ClientRpc’s, but instead of calling a function on the game object, they trigger Events instead. **IMPORTANT:** removed in version 18.0.0, see this [Issuearrow-up-right](https://github.com/vis2k/Mirror/pull/2178) for more information. * [SyncLists](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) SyncLists contain lists of values and synchronize data from servers to clients. * [SyncDictionary](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary) A SyncDictionary is an associative array containing an unordered list of key, value pairs. * [SyncHashSet](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synchashset) An unordered set of values that do not repeat. * [SyncSortedSet](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncsortedset) A sorted set of values that do not repeat. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#sync-to-owner) Sync To Owner ------------------------------------------------------------------------------------------------------------------- It is often the case when you don't want some player data visible to other players. In the inspector change the "Network Sync Mode" from "Observers" (default) to "Owner" to let Mirror know to synchronize the data only with the owning client. For example, suppose you are making an inventory system. Suppose player A,B and C are in the same area. There will be a total of 12 objects in the entire network: * Client A has Player A (himself), Player B and Player C * Client B has Player A , Player B (himself) and Player C * Client C has Player A , Player B and Player C (himself) * Server has Player A, Player B, Player C each one of them would have an Inventory component Suppose Player A picks up some loot. The server adds the loot to Player's A inventory, which would have a [SyncLists](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) of Items. By default, Mirror now has to synchronize player A's inventory everywhere, that means sending an update message to client A, client B and client C, because they all have a copy of Player A. This is wasteful, Client B and Client C do not need to know about Player's A inventory, they never see it on screen. It is also a security problem, someone could hack the client and display other people's inventory and use it to their advantage. If you set the "Network Sync Mode" in the Inventory component to "Owner", then Player A's inventory will only be synchronized with Client A. Now, suppose instead of 3 people you have 50 people in an area and one of them picks up loot. It means that instead of sending 50 messages to 50 different clients, you would only send 1. This can have a big impact in bandwith in your game. Other typical use cases include quests, player's hand in a card game, skills, experience, or any other data you don't need to share with other players. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#advanced-state-synchronization) Advanced State Synchronization ----------------------------------------------------------------------------------------------------------------------------------------------------- In most cases, the use of SyncVars is enough for your game scripts to serialize their state to clients. However in some cases you might require more complex serialization code. This page is only relevant for advanced developers who need customized synchronization solutions that go beyond Mirror’s normal SyncVar feature. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#custom-serialization-functions) Custom Serialization Functions ----------------------------------------------------------------------------------------------------------------------------------------------------- To perform your own custom serialization, you can implement virtual functions on NetworkBehaviour to be used for SyncVar serialization. These functions are: Use the `initialState` flag to differentiate between the first time a game object is serialized and when incremental updates can be sent. The first time a game object is sent to a client, it must include a full state snapshot, but subsequent updates can save on bandwidth by including only incremental changes. The `OnSerialize` function is only called for `initialState` or when the `NetworkBehaviour` is dirty. A `NetworkBehaviour` will only be dirty if a `SyncVar` or `SyncObject` (e.g. `SyncList`) has changed since the last OnSerialize call. After data has been sent the `NetworkBehaviour` will not be dirty again until the next `syncInterval` (set in the inspector). A `NetworkBehaviour` can also be marked as dirty by manually calling `SetDirtyBit` (this does not bypass the syncInterval limit). Although this works, it is usually better to let Mirror generate these methods and provide [custom serializers](https://mirror-networking.gitbook.io/docs/manual/guides/serialization) for your specific field. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#serialization-flow) Serialization Flow ----------------------------------------------------------------------------------------------------------------------------- Game objects with the Network Identity component attached can have multiple scripts derived from `NetworkBehaviour`. The flow for serializing these game objects is: On the server: * Each `NetworkBehaviour` has a dirty mask. This mask is available inside `OnSerialize` as `syncVarDirtyBits` * Each SyncVar in a `NetworkBehaviour` script is assigned a bit in the dirty mask. * Changing the value of SyncVars causes the bit for that SyncVar to be set in the dirty mask * Alternatively, calling `SetDirtyBit` writes directly to the dirty mask * NetworkIdentity game objects are checked on the server as part of it’s update loop * If any `NetworkBehaviours` on a `NetworkIdentity` are dirty, then an `UpdateVars` packet is created for that game object * The `UpdateVars` packet is populated by calling `OnSerialize` on each `NetworkBehaviour` on the game object * `NetworkBehaviours` that are not dirty write a zero to the packet for their dirty bits * `NetworkBehaviours` that are dirty write their dirty mask, then the values for the SyncVars that have changed * If `OnSerialize` returns true for a `NetworkBehaviour`, the dirty mask is reset for that `NetworkBehaviour` so it does not send again until its value changes. * The `UpdateVars` packet is sent to ready clients that are observing the game object On the client: * an `UpdateVars packet` is received for a game object * The `OnDeserialize` function is called for each `NetworkBehaviour` script on the game object * Each `NetworkBehaviour` script on the game object reads a dirty mask. * If the dirty mask for a `NetworkBehaviour` is zero, the `OnDeserialize` function returns without reading any more * If the dirty mask is non-zero value, then the `OnDeserialize` function reads the values for the SyncVars that correspond to the dirty bits that are set * If there are SyncVar hook functions, those are invoked with the value read from the stream. So for this script: The following sample shows the code that is generated by Mirror for the `SerializeSyncVars` function which is called inside `NetworkBehaviour.OnSerialize`: The following sample shows the code that is generated by Mirror for the `DeserializeSyncVars` function which is called inside `NetworkBehaviour.OnDeserialize`: If a `NetworkBehaviour` has a base class that also has serialization functions, the base class functions should also be called. Note that the `UpdateVar` packets created for game object state updates may be aggregated in buffers before being sent to the client, so a single transport layer packet may contain updates for multiple game objects. [PreviousSerializationchevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/serialization) [NextSyncVarschevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars) Last updated 10 months ago * [Sync To Owner](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#sync-to-owner) * [Advanced State Synchronization](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#advanced-state-synchronization) * [Custom Serialization Functions](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#custom-serialization-functions) * [Serialization Flow](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization#serialization-flow) Copy public virtual void OnSerialize(NetworkWriter writer, bool initialState); Copy public virtual void OnDeserialize(NetworkReader reader, bool initialState); Copy public class data : NetworkBehaviour { [SyncVar(hook = nameof(OnInt1Changed))] public int int1 = 66; [SyncVar] public int int2 = 23487; [SyncVar] public string MyString = "Example string"; void OnInt1Changed(int oldValue, int newValue) { // do something here } } Copy public override void SerializeSyncVars(NetworkWriter writer, bool initialState) { // Write any SyncVars in base class base.SerializeSyncVars(writer, forceAll); if (initialState) { // The first time a game object is sent to a client, send all the data (and no dirty bits) writer.WritePackedUInt32((uint)this.int1); writer.WritePackedUInt32((uint)this.int2); writer.Write(this.MyString); } else { // Writes which SyncVars have changed writer.WritePackedUInt64(base.syncVarDirtyBits); if ((base.get_syncVarDirtyBits() & 1u) != 0u) writer.WritePackedUInt32((uint)this.int1); if ((base.get_syncVarDirtyBits() & 2u) != 0u) writer.WritePackedUInt32((uint)this.int2); if ((base.get_syncVarDirtyBits() & 4u) != 0u) writer.Write(this.MyString); } } Copy public override void DeserializeSyncVars(NetworkReader reader, bool initialState) { // Read any SyncVars in base class base.DeserializeSyncVars(reader, initialState); if (initialState) { // The first time a game object is sent to a client, read all the data (and no dirty bits) int oldInt1 = this.int1; this.int1 = (int)reader.ReadPackedUInt32(); // if old and new values are not equal, call hook if (!base.SyncVarEqual(num, ref this.int1)) { this.OnInt1Changed(num, this.int1); } this.int2 = (int)reader.ReadPackedUInt32(); this.MyString = reader.ReadString(); return; } int dirtySyncVars = (int)reader.ReadPackedUInt32(); // is 1st SyncVar dirty if ((dirtySyncVars & 1) != 0) { int oldInt1 = this.int1; this.int1 = (int)reader.ReadPackedUInt32(); // if old and new values are not equal, call hook if (!base.SyncVarEqual(num, ref this.int1)) { this.OnInt1Changed(num, this.int1); } } // is 2nd SyncVar dirty if ((dirtySyncVars & 2) != 0) { this.int2 = (int)reader.ReadPackedUInt32(); } // is 3rd SyncVar dirty if ((dirtySyncVars & 4) != 0) { this.MyString = reader.ReadString(); } } --- # SyncLists | Mirror SyncLists are array based lists similar to C# [Listarrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netframework-4.7.2) that synchronize their contents from the server to the clients. A SyncList can contain any [supported mirror type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) . [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists#usage) Usage ------------------------------------------------------------------------------------------------------------- circle-info SyncList must be declared **readonly** and initialized in the constructor. circle-exclamation Note that by the time you wire up the Action handlers, the list will already be initialized, so they will not get invoked for the initial data, only updates. Copy using UnityEngine; using Mirror; public class SyncListExample : NetworkBehaviour { public readonly SyncList namesList = new SyncList(); public override void OnStartClient() { // Add handlers for SyncList Actions namesList.OnAdd += OnItemAdded; namesList.OnInsert += OnItemInserted; namesList.OnSet += OnItemChanged; namesList.OnRemove += OnItemRemoved; namesList.OnClear += OnListCleared; // OnChange is a catch-all event that is called for any change // to the list. It is called after the specific events above. // Strongly recommended to use the specific events above instead! namesList.OnChange += OnListChanged; // List is populated before handlers are wired up so we // need to manually invoke OnAdd for each element. for (int i = 0; i < namesList.Count; i++) namesList.OnAdd.Invoke(i); } public override void OnStopClient() { // Remove handlers when client stops namesList.OnAdd -= OnItemAdded; namesList.OnInsert -= OnItemInserted; namesList.OnSet -= OnItemChanged; namesList.OnRemove -= OnItemRemoved; namesList.OnClear -= OnListCleared; namesList.OnChange -= OnListChanged; } void OnItemAdded(int index) { Debug.Log($"Element added at index {index} {namesList[index]}"); } void OnItemInserted(int index) { Debug.Log($"Element inserted at index {index} {namesList[index]}"); } void OnItemChanged(int index, string oldValue) { Debug.Log($"Element changed at index {index} from {oldValue} to {namesList[index]}"); } void OnItemRemoved(int index, string oldValue) { Debug.Log($"Element removed at index {index} {oldValue}"); } void OnListCleared() { // OnListCleared is called before the list is actually cleared // so we can iterate the list to get the elements if needed. foreach (string name in namesList) Debug.Log($"Element cleared {name}"); } // OnListChanged is a catch-all event that is called for any change // to the list. It is called after the specific events above. // // NOTE: It's strongly recommended to use the specific events above instead! // // For OP_ADD and OP_INSERT, the value param is the NEW entry. // For OP_SET and OP_REMOVEAT, the value param is the OLD entry. // For OP_CLEAR, the param is null / default but you can iterate the list. void OnListChanged(SyncList.Operation op, int index, string value) { switch (op) { case SyncList.Operation.OP_ADD: // value is the NEW value of the entry Debug.Log($"Element added at index {index} {value}"); break; case SyncList.Operation.OP_INSERT: // value is the NEW value of the entry Debug.Log($"Element inserted at index {index} {value}"); break; case SyncList.Operation.OP_SET: // value is the OLD value of the entry Debug.Log($"Element changed at index {index} from {value} to {namesList[index]}"); break; case SyncList.Operation.OP_REMOVEAT: // value is the OLD value of the entry Debug.Log($"Element removed at index {index} was {value}"); break; case SyncList.Operation.OP_CLEAR: // value is null / default // we can iterate the list to get the elements if needed. foreach (string name in namesList) Debug.Log($"Element cleared {name}"); break; } } } [PreviousSyncEvent (Obsolete)chevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncevent) [NextSyncDictionarychevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary) Last updated 1 year ago --- # Pickups, Drops, and Child Objects | Mirror Frequently the question comes up about how to handle objects that are attached as children of the player prefab that all clients need to know about and synchronize, such as which weapon is equipped, picking up networked scene objects, and players dropping objects into the scene. circle-exclamation Mirror cannot support multiple Network Identity components within an object hierarchy. Since the Player object must have a Network Identity, none of its descendant objects can have one. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects#child-objects) Child Objects ----------------------------------------------------------------------------------------------------------------------------------------------- Let's start with the simple case of a single attachment point that is somewhere down the hierarchy of our Player, such as a hand at the end of an arm. In a script that inherits from NetworkBehaviour on the Player Prefab, we'd have a `GameObject` reference where the attachment point can be assigned in the inspector, a SyncVar enum with various choices of what the player is holding, and and a Hook for the SyncVar to swap out the art of the held item based on the new value. In the image below, Kyle has an empty game object, `RightHand`, added to the wrist, and some prefabs to be equipped (Ball, Box, Cylinder), and a Player Equip script to handle them. circle-info **NOTE**: The item prefabs are _art only_...they have no scripts, and they _must not_ have networking components. They can have monobehaviour-based scripts, of course, which can be referenced and called from ClientRpc's on the player prefab. The inspector shows `RightHand` assigned in 2 places, the Player Equip script, as well as the target of the 2nd Network Transform component, so we could adjust the relative position of the attachment point (not the art) for all clients as needed. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNFIm_Kt_Cnxc4elv4%252F-MUNFPRUeknH_cTvoDB6%252Fimage.png%3Falt%3Dmedia%26token%3De4c6a695-de4b-42e6-938d-0f3272698d8b&width=768&dpr=3&quality=100&sign=250248c0&sv=2) Below is the Player Equip script to handle the changing of the equipped item, and some notes for consideration: * While we could just have all the art items attached at design time and just enable / disable them based on the enum, this doesn't scale well to a lot of items and if they have scripts on them for how they behave in the game, such as animations, special effects, etc. it could get ugly pretty fast, so this example locally instantiates and destroys instead as a design choice. * The example makes no effort to deal with position offset between the item and the attach point, e.g. having the grip or handle of an item align with the hand. This is best dealt with in a monobehaviour script on the item that has public fields for the local position and rotation that can be set in the designer and a bit of code in Start to apply those values in local coordinates relative to the parent attach point. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects#dropping-items) Dropping Items ------------------------------------------------------------------------------------------------------------------------------------------------- Now that we can equip the items, we need a way to drop the current item into the world as a networked item. Remember that, as child art, the item prefabs have no networking components on them at all. First, let's add one more Input to the Update method above, and a `CmdDropItem` method: In the image above, there's a `sceneObjectPrefab` field that is assigned to a prefab that will act as a container for our item prefabs. The SceneObject prefab has a SceneObject script with a SyncVar like the Player Equip script, and a SetEquippedItem method that takes the shared enum value as a parameter. In the run-time image below, the Ball(Clone) is attached to the `RightHand` object, and the Box(Clone) is attached to the SceneObject(Clone), which is shown in the inspector. circle-info The art prefabs have simple colliders on them (sphere, box, capsule). If your art item has a mesh collider, it must be marked as Convex to work with the RigidBody on the SceneObject container. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MUNFIm_Kt_Cnxc4elv4%252F-MUNFYTK2FA-E2e7igfe%252Fimage.png%3Falt%3Dmedia%26token%3Da361f2ad-c6cb-4f69-b61a-07c193fabfe3&width=768&dpr=3&quality=100&sign=dfccc97d&sv=2) [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects#pickup-items) Pickup Items --------------------------------------------------------------------------------------------------------------------------------------------- Now that we have a box dropped in the scene, we need to pick it up again. To do that, a `CmdPickupItem` method is added to the Player Equip script: This method is simply called from `OnMouseDown` in the Scene Object script: Since the SceneObject(Clone) is networked, we can pass it directly through to `CmdPickupItem` on the player object to set the equipped item SyncVar and destroy the scene object. For this entire example, the only prefab that needs to be registered with Network Manager besides the Player is the SceneObject prefab. [PreviousScene GameObjectschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/scene-gameobjects) [NextExampleschevron-right](https://mirror-networking.gitbook.io/docs/manual/examples) Last updated 2 years ago * [Child Objects](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects#child-objects) * [Dropping Items](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects#dropping-items) * [Pickup Items](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/pickups-drops-and-child-objects#pickup-items) Copy using UnityEngine; using System.Collections; using Mirror; public enum EquippedItem : byte { nothing, ball, box, cylinder } public class PlayerEquip : NetworkBehaviour { public GameObject sceneObjectPrefab; public GameObject rightHand; public GameObject ballPrefab; public GameObject boxPrefab; public GameObject cylinderPrefab; [SyncVar(hook = nameof(OnChangeEquipment))] public EquippedItem equippedItem; void OnChangeEquipment(EquippedItem oldEquippedItem, EquippedItem newEquippedItem) { StartCoroutine(ChangeEquipment(newEquippedItem)); } // Since Destroy is delayed to the end of the current frame, we use a coroutine // to clear out any child objects before instantiating the new one IEnumerator ChangeEquipment(EquippedItem newEquippedItem) { while (rightHand.transform.childCount > 0) { Destroy(rightHand.transform.GetChild(0).gameObject); yield return null; } switch (newEquippedItem) { case EquippedItem.ball: Instantiate(ballPrefab, rightHand.transform); break; case EquippedItem.box: Instantiate(boxPrefab, rightHand.transform); break; case EquippedItem.cylinder: Instantiate(cylinderPrefab, rightHand.transform); break; } } void Update() { if (!isLocalPlayer) return; if (Input.GetKeyDown(KeyCode.Alpha0) && equippedItem != EquippedItem.nothing) CmdChangeEquippedItem(EquippedItem.nothing); if (Input.GetKeyDown(KeyCode.Alpha1) && equippedItem != EquippedItem.ball) CmdChangeEquippedItem(EquippedItem.ball); if (Input.GetKeyDown(KeyCode.Alpha2) && equippedItem != EquippedItem.box) CmdChangeEquippedItem(EquippedItem.box); if (Input.GetKeyDown(KeyCode.Alpha3) && equippedItem != EquippedItem.cylinder) CmdChangeEquippedItem(EquippedItem.cylinder); } [Command] void CmdChangeEquippedItem(EquippedItem selectedItem) { equippedItem = selectedItem; } } Copy void Update() { if (!isLocalPlayer) return; if (Input.GetKeyDown(KeyCode.Alpha0) && equippedItem != EquippedItem.nothing) CmdChangeEquippedItem(EquippedItem.nothing); if (Input.GetKeyDown(KeyCode.Alpha1) && equippedItem != EquippedItem.ball) CmdChangeEquippedItem(EquippedItem.ball); if (Input.GetKeyDown(KeyCode.Alpha2) && equippedItem != EquippedItem.box) CmdChangeEquippedItem(EquippedItem.box); if (Input.GetKeyDown(KeyCode.Alpha3) && equippedItem != EquippedItem.cylinder) CmdChangeEquippedItem(EquippedItem.cylinder); if (Input.GetKeyDown(KeyCode.X) && equippedItem != EquippedItem.nothing) CmdDropItem(); } Copy [Command] void CmdDropItem() { // Instantiate the scene object on the server Vector3 pos = rightHand.transform.position; Quaternion rot = rightHand.transform.rotation; GameObject newSceneObject = Instantiate(sceneObjectPrefab, pos, rot); // set the RigidBody as non-kinematic on the server only (isKinematic = true in prefab) newSceneObject.GetComponent().isKinematic = false; SceneObject sceneObject = newSceneObject.GetComponent(); // set the child object on the server sceneObject.SetEquippedItem(equippedItem); // set the SyncVar on the scene object for clients sceneObject.equippedItem = equippedItem; // set the player's SyncVar to nothing so clients will destroy the equipped child item equippedItem = EquippedItem.nothing; // Spawn the scene object on the network for all to see NetworkServer.Spawn(newSceneObject); } Copy using UnityEngine; using System.Collections; using Mirror; public class SceneObject : NetworkBehaviour { [SyncVar(hook = nameof(OnChangeEquipment))] public EquippedItem equippedItem; public GameObject ballPrefab; public GameObject boxPrefab; public GameObject cylinderPrefab; void OnChangeEquipment(EquippedItem oldEquippedItem, EquippedItem newEquippedItem) { StartCoroutine(ChangeEquipment(newEquippedItem)); } // Since Destroy is delayed to the end of the current frame, we use a coroutine // to clear out any child objects before instantiating the new one IEnumerator ChangeEquipment(EquippedItem newEquippedItem) { while (transform.childCount > 0) { Destroy(transform.GetChild(0).gameObject); yield return null; } // Use the new value, not the SyncVar property value SetEquippedItem(newEquippedItem); } // SetEquippedItem is called on the client from OnChangeEquipment (above), // and on the server from CmdDropItem in the PlayerEquip script. public void SetEquippedItem(EquippedItem newEquippedItem) { switch (newEquippedItem) { case EquippedItem.ball: Instantiate(ballPrefab, transform); break; case EquippedItem.box: Instantiate(boxPrefab, transform); break; case EquippedItem.cylinder: Instantiate(cylinderPrefab, transform); break; } } } Copy // CmdPickupItem is public because it's called from a script on the SceneObject [Command] public void CmdPickupItem(GameObject sceneObject) { // set the player's SyncVar so clients can show the equipped item equippedItem = sceneObject.GetComponent().equippedItem; // Destroy the scene object NetworkServer.Destroy(sceneObject); } Copy void OnMouseDown() { NetworkClient.localPlayer.GetComponent().CmdPickupItem(gameObject); } --- # Deprecations | Mirror Certain features of Unity Networking (UNet) were removed from Mirror or modified for various reasons. This page will identify all changed and removed features, properties, and methods, the reason for change or removal, and possible alternatives. circle-info **Note:** Some changes in this document may apply to an upcoming release to the Asset Store. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#match-namespace--host-migration) Match Namespace & Host Migration ------------------------------------------------------------------------------------------------------------------------------------------------------ As part of the Unity Services, this entire namespace was removed. It didn't work well to begin with, and was incredibly complex to be part of the core networking package. We expect this, along with other back-end services, will be provided through standalone apps that have integration to Mirror. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-server-simple) Network Server Simple --------------------------------------------------------------------------------------------------------------------------------- This was too complex and impractical to maintain for what little it did, and was removed. There are much easier ways to make a basic listen server, with or without one of our transports. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#couch-co-op) Couch Co-Op ------------------------------------------------------------------------------------------------------------- The core networking was greatly simplified by removing this low-hanging fruit. It was buggy, and too convoluted to be worth fixing. For those that need something like this, consider defining a non-visible player prefab as a message conduit that spawns actual player prefabs with client authority. All inputs would route through the conduit prefab to control the player objects. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#message-types) Message Types ----------------------------------------------------------------------------------------------------------------- The `MsgType` enumeration was removed. All message types are generated dynamically. Use `Send` instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-transform) Network Transform ------------------------------------------------------------------------------------------------------------------------- [Network Transform](https://mirror-networking.gitbook.io/docs/manual/components/network-transform) was fully replaced so that it only syncs position, rotation and scale, has control options for those and whether to interpolate them, and uses Snapshot Interpolation. It also has a bunch of virtual methods and there's a [Script Template](https://mirror-networking.gitbook.io/docs/manual/general/script-templates) for making your own derived version. Rigidbody support was removed in favor of a separate [Network Rigidbody](https://mirror-networking.gitbook.io/docs/manual/components/network-rigidbody) component. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-animator) Network Animator ----------------------------------------------------------------------------------------------------------------------- [Network Animator](https://mirror-networking.gitbook.io/docs/manual/components/network-animator) was also simplified, as it batches all Animator parameters into a single update message. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncvar-hook-parameters) SyncVar Hook Parameters ------------------------------------------------------------------------------------------------------------------------------------- [SyncVar](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncvars) property values are now updated before the hook is called, and hooks now require two parameters of the same type as the property: `oldValue` and `newValue` [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncliststruct) SyncListSTRUCT ------------------------------------------------------------------------------------------------------------------- Use [SyncList](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#synclist-classes) SyncList Classes ----------------------------------------------------------------------------------------------------------------------- * `SyncListString` was replaced by `SyncList` . * `SyncListFloat` was replaced by `SyncList`. * `SyncListInt` was replaced by `SyncList`. * `SyncListUInt` was replaced by `SyncList`. * `SyncListBool` was replaced by `SyncList`. See [documentation](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) for more details. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#synclist-operations) SyncList Operations ----------------------------------------------------------------------------------------------------------------------------- * `OP_REMOVE` was replaced by `OP_REMOVEAT` * `OP_DIRTY` was replaced by `OP_SET` See [documentation](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) for more details. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncidictionary-operations) SyncDictionary Operations ------------------------------------------------------------------------------------------------------------------------------------------ * `OP_DIRTY` was replaced by `OP_SET` See [documentation](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary) for more details. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncobject) SyncObject ----------------------------------------------------------------------------------------------------------- * This is now a class instead of an interface. * `Flush` - Use `ClearChanges` instead. [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#quality-of-service-flags) Quality of Service Flags --------------------------------------------------------------------------------------------------------------------------------------- In classic UNet, QoS Flags were used to determine how packets got to the remote end. For example, if you needed a packet to be prioritized in the queue, you would specify a high priority flag which the Unity LLAPI would then receive and deal with appropriately. Unfortunately, this caused a lot of extra work for the transport layer and some of the QoS flags did not work as intended due to buggy code that relied on too much magic. In Mirror, QoS flags were replaced with a "Channels" system. While the default transport, [Telepathy](https://mirror-networking.gitbook.io/docs/manual/transports/telepathy-transport) , does not use channels at all because it's TCP-based, other transports, such as [Ignorance](https://mirror-networking.gitbook.io/docs/manual/transports/ignorance) and [LiteNetLib](https://mirror-networking.gitbook.io/docs/manual/transports/litenetlib-transport) , do support them. The currently defined channels are: * `Channels.Reliable = 0` * `Channels.Unreliable = 1` [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#changes-by-class) Changes by Class ----------------------------------------------------------------------------------------------------------------------- ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkmanager) NetworkManager * `NetworkConnection` was replaced by `NetworkConnectionToClient` in many places. * `networkPort` Removed as part of separating Transports to components. Not all transports use ports, but those that do have a field for it. See [Transports](https://mirror-networking.gitbook.io/docs/manual/transports) for more info. * `IsHeadless()` Use compiler symbol `UNITY_SERVER` instead. * `ConfigureServerFrameRate` was renamed to `ConfigureHeadlessFrameRate`. * `client` Use NetworkClient directly, it will be made static soon. For example, use `NetworkClient.Send(message)` instead of `NetworkManager.client.Send(message)`. * `IsClientConnected()` Use static property `NetworkClient.isConnected` instead. * `onlineScene` and `offlineScene` These store full paths now, so use SceneManager.GetActiveScene().path instead. * `OnStartClient(NetworkClient client)` Override OnStartClient() instead since all `NetworkClient` methods are static now. * `OnClientChangeScene(string newSceneName)` Override `OnClientChangeScene(string newSceneName, SceneOperation sceneOperation, bool customHandling)` instead. * `OnClientChangeScene(string newSceneName, SceneOperation sceneOperation)` Override `OnClientChangeScene(string newSceneName, SceneOperation sceneOperation, bool customHandling)` instead. * `OnServerAddPlayer(NetworkConnection conn, AddPlayerMessage extraMessage)` Override `OnServerAddPlayer(NetworkConnection conn)` instead. See [Custom Player Spawn Guide](https://mirror-networking.gitbook.io/docs/manual/guides/gameobjects/custom-character-spawning) for details. * `OnServerRemovePlayer(NetworkConnection conn, NetworkIdentity player)` Use `NetworkServer.RemovePlayerForConnection(NetworkConnection conn, GameObject player, bool keepAuthority = false)` instead. * `OnServerError(NetworkConnection conn, int errorCode)` Replaced with `OnServerError(NetworkConnection conn, Exception exception)`. * `OnClientError(NetworkConnection conn, int errorCode)` Replaced with `OnClientError(Exception exception)`. * `disconnectInactiveConnections` and `disconnectInactiveTimeout` were removed. * OnClient\* virtual methods no longer take a `NetworkConnection` parameter. Remove the parameter from your overrides and use `NetworkClient.connection` in your code instead. * `serverTickRate` renamed to `sendRate`. * `serverTickInterval` moved to `NetworkServer`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkmanagerhud) NetworkManagerHUD * `showGUI` was removed. Disable the component instead. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkroommanager) NetworkRoomManager * `NetworkConnection` was replaced by `NetworkConnectionToClient` in many places. * `OnRoomServerCreateGamePlayer(NetworkConnection conn)` Use `OnRoomServerCreateGamePlayer(NetworkConnection conn, GameObject roomPlayer)` instead. * `OnRoomServerSceneLoadedForPlayer(GameObject roomPlayer, GameObject gamePlayer)` Use `OnRoomServerSceneLoadedForPlayer(NetworkConnection conn, GameObject roomPlayer, GameObject gamePlayer)` instead. * Client virtual methods no longer take a `NetworkConnection` parameter. Use `NetworkClient.connection` within your overrides. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkidentity) NetworkIdentity * `clientAuthorityOwner` Use connectionToClient instead * `GetSceneIdenity` Use `GetSceneIdentity` instead (typo in original name) * `RemoveClientAuthority(NetworkConnection conn)` NetworkConnection parameter is no longer needed and nothing is returned * `spawned` dictionary This has been split up to `NetworkServer.spawned` and `NetworkClient.spawned` dictionaries. * Local Player Authority checkbox This checkbox is no longer needed, and we simplified how [Authority](https://mirror-networking.gitbook.io/docs/manual/guides/authority) works in Mirror. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkbehaviour) NetworkBehaviour * `NetworkConnection` was replaced by `NetworkConnectionToClient` in many places. * `sendInterval` attribute Use `NetworkBehaviour.syncInterval` field instead. Can be modified in the Inspector too. * `List m_SyncObjects` Use `List syncObjects` instead. * `OnSetLocalVisibility(bool visible)` Override `OnSetHostVisibility(bool visible)` instead. * `OnRebuildObservers`, `OnCheckObserver`, and `OnSetHostVisibility` were moved to a separate class called `NetworkVisibility` * `NetworkBehaviour.OnNetworkDestroy` was renamed to `NetworkBehaviour.OnStopClient`. * `getSyncVarHookGuard` renamed to `GetSyncVarHookGuard`. * `setSyncVarHookGuard` - renamed to `SetSyncVarHookGuard`. * `SetDirtyBit` - Use `SetSyncVarDirtyBit` instead. * `[Command]` attribute parameter `ignoreAuthority` replaced with `requiresAuthority`. * `[ClientRpc]` attribute parameter `includeOwner` replace with `excludeOwner`. * `hasAuthority` renamed to `isOwned`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkconnection) NetworkConnection * `hostId` Removed because it's not needed ever since we removed LLAPI as default. It's always 0 for regular connections and -1 for local connections. Use `connection.GetType() == typeof(NetworkConnection)` to check if it's a regular or local connection. * `isConnected` Removed because it's pointless. A `NetworkConnection` is always connected. * `InvokeHandlerNoData(int msgType)` Use `InvokeHandler` instead. * `playerController` renamed to `identity` since that's what it is: the `NetworkIdentity` for the connection. * `RegisterHandler(short msgType, NetworkMessageDelegate handler)` Use `NetworkServer.RegisterHandler()` or `NetworkClient.RegisterHandler()` instead. * `UnregisterHandler(short msgType)` Use `NetworkServer.UnregisterHandler()` or `NetworkClient.UnregisterHandler()` instead. * `Send(int msgType, MessageBase msg, int channelId = Channels.Reliable)` Use `Send(msg, channelId)` instead. * `clientOwnedObjects` renamed to `owned`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkserver) NetworkServer * `NetworkConnection` was replaced by `NetworkConnectionToClient` in many places. * `FindLocalObject(uint netId)` Use `NetworkServer.spawned[netId].gameObject` instead. * `RegisterHandler(int msgType, NetworkMessageDelegate handler)` Use `RegisterHandler(T msg)` instead. * `RegisterHandler(MsgType msgType, NetworkMessageDelegate handler)` Use `RegisterHandler(T msg)` instead. * `RegisterHandler(Action handler, bool requireAuthentication = true)` Use `RegisterHandler(Action(T message, int channelId = Channels.Reliable)` instead. * `SendToReady(NetworkIdentity identity, short msgType, MessageBase msg, int channelId = Channels.Reliable)` Use `identity.connectionToClient.Send()` instead. * `SendToReady(NetworkIdentity identity, T message, bool includeOwner = true, int channelId = Channels.Reliable)` Renamed to `SendToReadyObservers`. * `SpawnWithClientAuthority(GameObject obj, GameObject player)` Use `Spawn(GameObject obj, GameObject player)` instead. * `SpawnWithClientAuthority(GameObject obj, NetworkConnection ownerConnection)` Use `Spawn(GameObject obj, NetworkConnection ownerConnection)` instead. * `SpawnWithClientAuthority(GameObject obj, Guid assetId, NetworkConnection ownerConnection)` Use `Spawn(GameObject obj, Guid assetId, NetworkConnection ownerConnection)` instead. * `disconnectInactiveConnections` and `disconnectInactiveTimeout` were removed. * `NoConnections` was renamed to `NoExternalConnections`. * `DisconnectAllExternalConnections` / `DisconnectAllConnections` Use `DisconnectAll` instead. * `OnError` renamed to `OnTransportError` for clarity. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkclient) NetworkClient * `NetworkClient singleton` Use `NetworkClient` directly. Singleton isn't needed anymore as all functions are static now. Example: `NetworkClient.Send(message)` instead of `NetworkClient.singleton.Send(message)`. * `allClients` Use `NetworkClient` directly instead. There is always exactly one client. * `GetRTT()` Use `NetworkTime.rtt` instead. * `readyConnection` Use `connection` instead. * `isLocalClient` Use `isHostClient` instead. * `DisconnectLocalServer()` Use `NetworkClient.Disconnect()` instead. * `RegisterHandler(int msgType, NetworkMessageDelegate handler)` Use `RegisterHandler(T msg)` instead. * `RegisterHandler(MsgType msgType, NetworkMessageDelegate handler)` Use `RegisterHandler(T msg)` instead. * `RegisterHandler(Action handler, bool requireAuthentication = true)` Use `RegisterHandler(Action handler, bool requireAuthentication = true)` instead. * `UnregisterHandler(int msgType)` Use `UnregisterHandler(T msg)` instead. * `UnregisterHandler(MsgType msgType)` Use `UnregisterHandler(T msg)` instead. * `Ready(NetworkConnection conn)` Use `Ready()` without the `NetworkConnection` parameter instead. * `Send(short msgType, MessageBase msg)` Use `Send(T msg, int channelId = Channels.Reliable)` with no message id instead * `ShutdownAll()` Use `Shutdown()` instead. There is only one client. * `OnError` renamed to `OnTransportError` for clarity. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#clientscene) ClientScene * Merged into `NetworkClient`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-scene-checker) Network Scene Checker * Replaced by [Scene Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/scene) . ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-proximity-checker) Network Proximity Checker * Replaced by [Spatial Hash](https://mirror-networking.gitbook.io/docs/manual/interest-management/spatial-hashing) / [Distance](https://mirror-networking.gitbook.io/docs/manual/interest-management/distance) Interest Management. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-match-checker) Network Match Checker * Replaced by Network Match and requires [Match Interest Managemen](https://mirror-networking.gitbook.io/docs/manual/interest-management/match) t. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-owner-checker) Network Owner Checker * Replaced by Network Team and requires [Team Interest Management](https://mirror-networking.gitbook.io/docs/manual/interest-management/team) . ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-authenticator) Network Authenticator * `NetworkConnection` was replaced by `NetworkConnectionToClient` in many places. * `OnClientAuthenticate` no longer takes a `NetworkConnection` parameter. Use `NetworkClient.connection` as needed. * `OnClientAuthenticated` event no longer takes a `NetworkConnection` parameter. Use `NetworkClient.connection` as needed. * `NetworkConnection` is no longer used in client message handlers. Use `NetworkClient.connection` within your handlers instead. * `ClientAccept` and `ClientReject` no longer needs a `NetworkConnection` parameter. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networktime) NetworkTime * `NetworkTime.timeVar` was renamed to `timeVariance`. * `NetworkTime.timeSd` was renamed to `timeStandardDeviation`. * `NetworkTime.rttVar` was renamed to `rttVariance`. * `NetworkTime.rttSd` was renamed to `rttStandardDeviation`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#transport) Transport * `activeTransport` renamed to `active`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#messages) Messages Basic messages of simple types were all removed as unnecessary bloat. You can create your own message classes instead. * `StringMessage` * `ByteMessage` * `BytesMessage` * `IntegerMessage` * `DoubleMessage` * `EmptyMessage` NetworkMessage requires structs in all cases - classes no longer supported ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkreader) NetworkReader * `Read(byte[] buffer, int offset, int count)` Use `ReadBytes` instead. * `ReadPackedInt32(int value)` Use `ReadInt32(int value)` instead. * `ReadPackedUInt32(uint value)` Use `ReadUInt32(uint value)` instead. * `ReadPackedUInt64(ulong value)` Use `ReadUInt64(ulong value)` instead. * `ReadBoolean` renamed to `ReadBool`. * `ReadInt16` renamed to `ReadShort`. * `ReadInt32` renamed to `ReadInt`. * `Readint64` renamed to `ReadLong`. * `ReadSingle` renamed to `ReadFloat`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkwriter) NetworkWriter * `Write(bool value)` Use `WriteBool` instead. * `Write(byte value)` Use `WriteByte` instead. * `Write(sbyte value)` Use `WriteSByte` instead. * `Write(short value)` Use `WriteShort` instead. * `Write(ushort value)` Use `WriteUShort` instead. * `Write(int value)` Use `WriteInt` instead. * `Write(uint value)` Use `WriteUInt` instead. * `Write(long value)` Use `WriteLong` instead. * `Write(ulong value)` Use `WriteULong` instead. * `Write(float value)` Use `WriteFloat` instead. * `Write(double value)` Use `WriteDouble` instead. * `Write(decimal value)` Use `WriteDecimal` instead. * `Write(string value)` Use `WriteString` instead. * `Write(char value)` Use `WriteChar` instead. * `Write(Vector2 value)` Use `WriteVector2` instead. * `Write(Vector2Int value)` Use `WriteVector2Int` instead. * `Write(Vector3 value)` Use `WriteVector3` instead. * `Write(Vector3Int value)` Use `WriteVector3Int` instead. * `Write(Vector4 value)` Use `WriteVector4` instead. * `Write(Color value)` Use `WriteColor` instead. * `Write(Color32 value)` Use `WriteColor32` instead. * `Write(Guid value)` Use `WriteGuid` instead. * `Write(Transform value)` Use `WriteTransform` instead. * `Write(Quaternion value)` Use `WriteQuaternion` instead. * `Write(Rect value)` Use `WriteRect` instead. * `Write(Plane value)` Use `WritePlane` instead. * `Write(Ray value)` Use `WriteRay` instead. * `Write(Matrix4x4 value)` Use `WriteMatrix4x4` instead. * `Write(NetworkIdentity value)` Use `WriteNetworkIdentity` instead. * `Write(GameObject value)` Use `WriteGameObject` instead. * `Write(byte[] buffer, int offset, int count)` Use `WriteBytes` instead. * `WritePackedInt32(int value)` Use `WriteInt32(int value)` instead * `WritePackedUInt32(uint value)` Use `WriteUInt32(uint value)` instead * `WritePackedUInt64(ulong value)` Use `WriteUInt64(ulong value)` instead ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#remotecallhelper) RemoteCallHelper * Renamed to `RemoteProcedureCalls`. * `CmdDelegate` renamed to `RemoteCallDelegate`. * `MirrorInvokeType` renamed to `RemoteCallType`. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#transport-1) Transport * `GetConnectionInfo(int connectionId, out string address)` Use `ServerGetClientAddress(int connectionId)` instead. * `GetMaxBatchSize` renamed to `GetMaxPacketSize`. * `ClientSend(int channelId, ArraySegment segment)` Use `ClientSend(segment, channelId)` instead. * `ServerSend(int connectionId, int channelId, ArraySegment segment)` Use `ServerSend(connectionId, segment, channelId)` instead. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#telepathytransport) Telepathy Transport * `MaxMessageSize` Use `MaxMessageSizeFromClient` or `MaxMessageSizeFromServer` instead. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#fallback-transport) Fallback Transport * This has been removed. ### [hashtag](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#utils) Utils * `Version` enum removed. * `DefaultReliable` renamed to `Reliable`. * `DefaultUnreliable` renamed to `Unreliable`. [Previous2019 Change Logchevron-left](https://mirror-networking.gitbook.io/docs/manual/general/changelog/2019-change-log) [NextMigration Guidechevron-right](https://mirror-networking.gitbook.io/docs/manual/general/migration-guide) Last updated 3 years ago * [Match Namespace & Host Migration](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#match-namespace--host-migration) * [Network Server Simple](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-server-simple) * [Couch Co-Op](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#couch-co-op) * [Message Types](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#message-types) * [Network Transform](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-transform) * [Network Animator](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-animator) * [SyncVar Hook Parameters](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncvar-hook-parameters) * [SyncListSTRUCT](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncliststruct) * [SyncList Classes](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#synclist-classes) * [SyncList Operations](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#synclist-operations) * [SyncDictionary Operations](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncidictionary-operations) * [SyncObject](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#syncobject) * [Quality of Service Flags](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#quality-of-service-flags) * [Changes by Class](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#changes-by-class) * [NetworkManager](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkmanager) * [NetworkManagerHUD](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkmanagerhud) * [NetworkRoomManager](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkroommanager) * [NetworkIdentity](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkidentity) * [NetworkBehaviour](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkbehaviour) * [NetworkConnection](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkconnection) * [NetworkServer](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkserver) * [NetworkClient](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkclient) * [ClientScene](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#clientscene) * [Network Scene Checker](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-scene-checker) * [Network Proximity Checker](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-proximity-checker) * [Network Match Checker](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-match-checker) * [Network Owner Checker](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-owner-checker) * [Network Authenticator](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#network-authenticator) * [NetworkTime](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networktime) * [Transport](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#transport) * [Messages](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#messages) * [NetworkReader](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkreader) * [NetworkWriter](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#networkwriter) * [RemoteCallHelper](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#remotecallhelper) * [Transport](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#transport-1) * [Telepathy Transport](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#telepathytransport) * [Fallback Transport](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#fallback-transport) * [Utils](https://mirror-networking.gitbook.io/docs/manual/general/deprecations#utils) --- # Mirror Quick Start Project | Mirror This guide currently shows you: * [Basic scene setup](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-1) * [Player movement](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-4) * [Names and colours](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-8) * [Scene script with canvas buttons](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-11) * [Weapon switching](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-12) * [Networked scene objects tweak](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-15) * [Menu and scene switching](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-16) * [Weapon firing](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-20) It is best to first make a mini practice game before converting your single player game, or creating your ideal brand new multiplayer. The Pre-made Mirror examples are great for using as reference, it is recommend to use them regarding connection setup, with ports and firewalls. This can be a huge topic that changes from person to person, and is not covered in this guide, here we will use localHost (multiple games on same PC). **End Result:** ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3p4I2uOgS1uyDibfL%252FQS-image--036.jpg%3Falt%3Dmedia%26token%3Dbcf3e359-7ed7-4319-b9d2-7b47b0eaad05&width=768&dpr=3&quality=100&sign=ecc6780f&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-1) Part 1 Blank Project, import Mirror from [Asset Storearrow-up-right](https://assetstore.unity.com/packages/tools/network/mirror-129321) . ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-2) Part 2 * Create new scene, save it, and add it to build settings * Create a new GameObject, name it NetworkManager in the scene, and add these 3 components * NetworkManager * KCPTransport (TelepathyTransport is older, you do not need KCP and Telepathy) * NetworkManagerHUD * On the NetworkManager component, drag your Offline and Online scene into the slots, we have only one scene for now, so put your scene in both * The scene must be in the build settings before dragging it to the field ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kBKLFKS4iZitV8_y%252FQS-image--000.jpg%3Falt%3Dmedia%26token%3Db790a11c-ffab-473f-93a7-35f2ea9ad48a&width=768&dpr=3&quality=100&sign=79efb47f&sv=2) Note: KCP Transport has replaced Telepathy in newer versions ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kIQtGIFS_s7o1oW1%252FQS-image--001.jpg%3Falt%3Dmedia%26token%3D42f17191-3635-4efc-b1e5-7398dd717fc2&width=768&dpr=3&quality=100&sign=db16e880&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-3) Part 3 Setup the scene * Add a simple Plane floor with: * positions (0, -1, 0) * scale (2, 2, 2) * (optional) add a material to this, I added one called dirt that is used one of mirrors examples * Next we add a GameObject, name does not matter * Add `NetworkStartPosition` component to this GameObject * Duplicate the GameObject a few times, and scatter around your scene floor so that you have multiple spawn points. I did 4, one near each corner ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kQeUWjYyeKV39Zgz%252FQS-image--002.jpg%3Falt%3Dmedia%26token%3D34574ff2-2844-4539-a9a7-01e0fbbef44b&width=768&dpr=3&quality=100&sign=8e7ee6e4&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-4) Part 4 Creating the player * Create a capsule using the menus as shown in the image * Attached a NetworkTransform component, this will auto add a Network Identity * Tick Client Authority on the NetworkTransform (Note: Newer Mirror versions use "Sync Direction" set this to "Client To Server".) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kTlcgGYibMpokrdV%252FQS-image--003.jpg%3Falt%3Dmedia%26token%3D622663ed-df02-48a1-bcd8-d99061a5eb53&width=768&dpr=3&quality=100&sign=785240c4&sv=2) * Rename that object Player * Add an empty PlayerScript * Drag into Project to create a prefab * Then delete Player from scene ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kXsSibU1gFmAIiSB%252FQS-image--004.jpg%3Falt%3Dmedia%26token%3D85beae45-48ea-4cdf-bae8-f336398171a5&width=768&dpr=3&quality=100&sign=2311134e&sv=2) * Drag your player prefab into Network manager, * Set spawn method to Round Robin. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F4df316f9b67926e9af845e7edcecc4abea3f4edd.jpg%3Fgeneration%3D1600508401482030%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=4c44aa05&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-5) Part 5 Add the following to your PlayerScript. ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-6) Part 6 Press play in Unity editor, and then Host (server + client) button in the game window. You should be able to move around with a first person view capsule. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kfhhgCS3K5aXqh5F%252FQS-image--006.jpg%3Falt%3Dmedia%26token%3D7e21a083-cd2f-42c9-b643-f0388c6eacd6&width=768&dpr=3&quality=100&sign=1aeb08a5&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-7) Part 7 Build and run your scene, open it, host on one, and press the Client button on the other. Congrats you made a mini multiplayer game! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kl_h14szzfbIAQVK%252FQS-image--007.jpg%3Falt%3Dmedia%26token%3Dc66966cb-9437-4f79-9c3b-998569b0a029&width=768&dpr=3&quality=100&sign=5e1cf3b7&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-8) Part 8 Player name above heads * Inside your player Prefab, create an empty GameObject * name it something like `FloatingInfo` * position Y to 1.5 * scale X to -1 * Inside that `FloatingInfo`, create a 3D text using Unity menu (GameObject - 3D Object - 3D Text), * Set it up as shown in the picture below ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3koX3YJ0M3Vo99URL%252FQS-image--008.jpg%3Falt%3Dmedia%26token%3D5d233ce3-f24c-4cc4-b629-38c16f9eb654&width=768&dpr=3&quality=100&sign=bded8437&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-9) Part 9 Update your PlayerScript.cs with this: ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-10) Part 10 Add the `PlayerNameText` and `FloatingInfo` objects into the script on the player prefab, as shown below. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kruhKCkPlmR7UW6f%252FQS-image--009.jpg%3Falt%3Dmedia%26token%3D6f8cce87-17f8-48c0-91a8-3e4705d3c1a7&width=768&dpr=3&quality=100&sign=aff4666&sv=2) Now if you build and run, host on one, join on the other, you will see player names and colors synced across the network! Well done, 5 stars to you! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kuduqFjl4__p4FKF%252FQS-image--010.jpg%3Falt%3Dmedia%26token%3D21ec7d95-7de0-4f0c-9a24-665a1d106cd1&width=768&dpr=3&quality=100&sign=9631412&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-11) Part 11 A scene networked object all can access and adjust. Create a SceneScript.cs, add it onto an empty GameObject in the scene called SceneScript. Then create a Canvas with text and button, similar to below. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3kx3dMSAnWxced36O%252FQS-image--011.jpg%3Falt%3Dmedia%26token%3D63882f92-893a-490e-8581-61717bf8eef2&width=768&dpr=3&quality=100&sign=220fd53e&sv=2) Add the sceneScript variable, Awake function, and CmdSendPlayerMessage to PlayerScript.cs Also add the new playerName joined line to CmdSetupPlayer(); Add this code to SceneScript.cs * Attach the ButtonSendMessage function to your Canvas Button. * Attach Canvas Scene Text to SceneScript variable. * ignore SceneScript’s, playerScript variable, it automatically sets this! * Attach a NetworkIdentity component to the SceneScript gameobject, if it has not automatically done so. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2Fmirror-networking.com%2Fdocs%2FArticles%2FCommunityGuides%2FMirrorQuickStartGuide%2Fimage--012.jpg&width=768&dpr=3&quality=100&sign=b83c57c2&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3l-usVf9DhFprGZAl%252FQS-image--012.jpg%3Falt%3Dmedia%26token%3Dfb4b73c8-4098-4a13-a851-c2c7bb6fbffb&width=768&dpr=3&quality=100&sign=adeed675&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F0883cb33d0ca163a79fa758020168d13b7c3621b.jpg%3Fgeneration%3D1600508398682820%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=3062e719&sv=2) Now if you build and run, host and join, you can send messages, and have a text log for actions! Wahooo! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252F9ce78f0ad8fdff2cf408a2bf35e4854a82034240.jpg%3Fgeneration%3D1600508402698984%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=30ac5719&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252Fsync%252Fa092e9caec288cd4a3ef643206872ff4eda41608.jpg%3Fgeneration%3D1600508398351722%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=c1509679&sv=2) Experiment and adjust, have fun! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3hJhd1IeVPooHJAMg%252F-MV3lS2xRo5UkQyS4fSv%252FQS-image--016.jpg%3Falt%3Dmedia%26token%3D64f0e5b8-b98d-46dc-b065-aa030922b3cf&width=768&dpr=3&quality=100&sign=ee907912&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-12) Part 12 Weapon switching! The code bits. Add the following to your PlayerScript.cs Add the weapon switch button in update. Only local player switches its own weapon, so it goes below the `!isLocalPlayer` check. ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-13) Part 13 Weapon models Add the basic cube weapons first, change these later. * Double click your player prefab to enter it * Add a "WeaponsHolder" empty GameObject, with position and rotation at 0,0,0. * Inside that GameObject, create a cube from unity menu, (GameObject, 3D object, cube)- Remove the box colliders. * Rename this `Weapon1`, change position and scale to match the below pictures. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3neGeN6rcwdIp-Q-Q%252FQS-image--017.jpg%3Falt%3Dmedia%26token%3D5a023e33-a0b4-4666-8a96-fbaf41bde192&width=768&dpr=3&quality=100&sign=bd2efb32&sv=2) Duplicate weapon 1 for a Weapon 2, and change its scale and position, now you should have 2 different looking ‘weapons’! ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3nhuJnT5M_tjliKGi%252FQS-image--018.jpg%3Falt%3Dmedia%26token%3D2a27b220-249d-49a2-abe3-7135c54832ad&width=768&dpr=3&quality=100&sign=33342af3&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-14) Part 14 Weapon switch finale. * Add these 2 GameObjects to your PlayerScript.cs weapons array. * Disable weapon 2, so only weapon 1 shows when spawning. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3nqfB-evCoTvFe_dV%252FQS-image--019.jpg%3Falt%3Dmedia%26token%3D77015ced-07ec-4f68-be89-c60c70c5cc59&width=768&dpr=3&quality=100&sign=d3d017db&sv=2) Build and run! You should see each player switching weapons, and whatever your player has equipped, will auto show on new joining players (sync var and hook magic!) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3nt9kgu2EYKcmP1YI%252FQS-image--020.jpg%3Falt%3Dmedia%26token%3D524e5171-657e-4130-ad72-41ebabf74fb3&width=768&dpr=3&quality=100&sign=dbef2524&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-15) Part 15 Here we will make a small adjustment, as using a GameObject.Find() may not guarantee Network Identity scene objects are found. In the image below you can see our NetworkIdentity scene object gets disabled, as they are disabled until a player is in ‘ready’ status (ready status is usually set when player spawns). ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3nwa1nh71865uq0-q%252FQS-image--021.jpg%3Falt%3Dmedia%26token%3Dd7a89f4e-b512-4f4a-ab2b-08a2571e4250&width=768&dpr=3&quality=100&sign=ecc13827&sv=2) So our chosen workaround is to have our GameObject.Find() get the non-networked scene object, which will have those Network Identity scene object as pre-set variables. Create a new script called SceneReference.cs, and add this one variable. Open up SceneScript.cs and add the following variable. Now in your Unity scene create a gameobject, name it SceneReference, and add the new script. On both Scene gameobjects, set the reference to each other. So SceneReference can speak to SceneScript, and SceneScript to SceneReference. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3o0XjxVMqA2YAt3fm%252FQS-image--022.jpg%3Falt%3Dmedia%26token%3D44ff0388-93f2-49c9-901a-b05c16733a2c&width=768&dpr=3&quality=100&sign=617b184f&sv=2) Open up PlayerScript.cs and overwrite the Awake function to this: ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-16) Part 16 Menu and Scene switching, here we will go from an offline Menu, with a play button, to a Games List with a back button and the Host/Join HUD, to your online map, and then a second map for host to switch to. Open up SceneScript.cs and add the following function. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3o4itqWOLNfnRle4N%252FQS-image--023.jpg%3Falt%3Dmedia%26token%3D1ae74fd4-a9ba-4e7a-bc6b-8b9b66de41ad&width=768&dpr=3&quality=100&sign=982a0a4a&sv=2) Duplicate your previous Canvas button, rename it and reposition it, then setup the OnClick() to point to SceneScript.ButtonChangeScene, like in the image. Then drag your NetworkManager into your Project, to make it a Prefab, this way any changes we make later will apply to them all. If you haven’t already, you can sort out your project into folders, one for scripts, prefabs, scenes, textures etc. :) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3o81DA43ROutq5315%252FQS-image--024.jpg%3Falt%3Dmedia%26token%3D7542aa45-229f-4cdd-b1b0-ec221ba13955&width=768&dpr=3&quality=100&sign=a55bc4ce&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-17) Part 17 Save, and then Duplicate your MyScene, rename to make a Menu, GamesList and MyOtherScene, then add them to the build settings, with Menu being first. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oB_tj1bYcVfhjzjf%252FQS-image--025.jpg%3Falt%3Dmedia%26token%3Db4eda2dc-ba39-4a61-b5ae-3282b0ddf89d&width=768&dpr=3&quality=100&sign=74ec1deb&sv=2) Open up the Menu scene, remove the spawn points, SceneScript, SceneReference, Network Manager and Plane, so it looks like the below. Adjust the canvas button to say Play, centre it. Here is where you could add the Scores scene, Contact section, News, etc Create a Menu.cs script, add it onto a Menu gameObject. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oEOo_aTV1PzxZePo%252FQS-image--026.jpg%3Falt%3Dmedia%26token%3D0281fcc7-c2b1-48e7-abbb-f83fe0f43594&width=768&dpr=3&quality=100&sign=58f05521&sv=2) Add the code to Menu.cs, then in the Button, drag the Menu gameobject into the On Click () and set it to Menu.LoadScene, like in the picture. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oIPCjHZ2hFC2cRcq%252FQS-image--027.jpg%3Falt%3Dmedia%26token%3D7ee44058-2a98-45e0-a319-28080fa1bcb3&width=768&dpr=3&quality=100&sign=622ef8c4&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-18) Part 18 Open up GamesList scene, do similar to Menu but KEEP NetworkManager prefab. Create a GamesList.cs, add the code, and add it onto a GamesList gameobject in the scene. Adjust a canvas button to say Menu (this is our back button). It should look like the image below. * The games list is where you can add List server contents, or matchmaker, or just the host and join buttons, similar to the default NetworkManagerHud, for now leave this. :) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oMNs04WJFZONp-wi%252FQS-image--028.jpg%3Falt%3Dmedia%26token%3D7f0dc2e2-a845-4594-a06f-79409e7e8a66&width=768&dpr=3&quality=100&sign=2ae8894f&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-19) Part 19 Open MyOtherScene, this is our second map. Change the camera background colour and floor material (or anything, just so you can see both scenes are different. To summarise, MyScene is map 1 and MyOtherScene is map 2. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oQIxul3i8oSpFpNJ%252FQS-image--029.jpg%3Falt%3Dmedia%26token%3Da7fd8b22-d8dc-4601-a056-da860cfed69e&width=768&dpr=3&quality=100&sign=dd9c2026&sv=2) In your NetworkManager prefab in PROJECT (not the one in scenes), add Menu to offline, and MyScene to Online variables. This should change all the NetworkManager prefabs to have these settings. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oT8IYQOqTGftA8uD%252FQS-image--030.jpg%3Falt%3Dmedia%26token%3D295cd3ed-509b-48c2-8090-ef45b4a09fc5&width=768&dpr=3&quality=100&sign=897652c7&sv=2) Build and Run, press Play on the Menu to go to GamesList, then click Host (for player 1). For player 2, press Play on Menu, then client connect on GamesList. Now the host can change scenes between map 1 and map 2, and if anyone disconnects or stops the game, Menu scene is load to start again. This whole process can be tidied up, but should provide a good scene switch template to your Mirror game :) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-20) Part 20 Here we will add basic weapon firing, using rigidbody prefabs. Raycasts with a representation of the fired object is usually better to do this, and keep phycisal objects for things like Grenades and Cannon balls. This section will also lack a lot of security and anti-cheat techniques in order to keep the guide simple, but anyway, here we go! Double click the Player Prefab to open it, create empty gameobjects and line them up with the end of your weapon, add them as child to each weapon. Some weapons may be short pistols, others long rifles, so the place where objects spawn will be different. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oW2Q9OJ_lN7y9YUL%252FQS-image--031.jpg%3Falt%3Dmedia%26token%3D1161b6f4-a665-4948-ae09-642a81f197cb&width=768&dpr=3&quality=100&sign=aada27f8&sv=2) Create a Weapon.cs script, add it to the Weapon1 and Weapon 2 gameObjects inside the player prefab. ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-21) Part 21 Now back in your scene we shall make 2 bullets, in Unitys menu, go to GameObject, 3D Object, Sphere. Add rigidbody to this sphere, make the scale 0.2, 0.2, 0.2, then save it as a Prefab in the Project.
Do the same with a cube, so you have two different looking bullets. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oavDFfSjcHxR0Ofe%252FQS-image--032.jpg%3Falt%3Dmedia%26token%3D07ac9814-06bf-46f2-8b36-72a26fcb12dc&width=768&dpr=3&quality=100&sign=132a0820&sv=2) Inside your player prefab again, select a weapon, and set the variables on weapon script. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3odoE1t94o6UIA2pc%252FQS-image--033.jpg%3Falt%3Dmedia%26token%3Da1c94293-0fcd-4b31-ba0c-edcc7d40302d&width=768&dpr=3&quality=100&sign=75638f24&sv=2) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3oqD2r_5DJ-amKC14%252FQS-image--034.jpg%3Falt%3Dmedia%26token%3D1bd1af39-6e58-469d-8f05-74c10f1b50c8&width=768&dpr=3&quality=100&sign=df1aeee2&sv=2) ### [hashtag](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-22) Part 22 In SceneScript.cs, add this variable and function. Enter MyScene (map 1). Duplicate the Canvas StatusText, rename to Ammo, then drag that Ammo text UI into SceneScript gameobject, canvasAmmoText variable. Do this on BOTH MyScene (map 1) and MyOtherScene (map 2), as we have not yet linked or prefabbed our canvas and scene scripts to auto update changes on each map. ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3ovigJm0785Sb9C1z%252FQS-image--035.jpg%3Falt%3Dmedia%26token%3Dec97879d-1c7b-4963-a41c-5fd727fa116b&width=768&dpr=3&quality=100&sign=c3608b96&sv=2) Open up PlayerScript.cs, add these two variables: In the ‘OnWeaponChanged’ function, update it with the new line, so it should look like this.
 In Awake(), add this at the end: In Update(), add this at the end: Add these two functions after the Update() {} function finishes. Build and Run, you should have firing, with different speeds and cooldowns on all players :) ![](https://mirror-networking.gitbook.io/docs/~gitbook/image?url=https%3A%2F%2F462154250-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-MGmQrf2z6FL0ZpExPAn%252F-MV3m9cU1TxAlfbLpppU%252F-MV3p4I2uOgS1uyDibfL%252FQS-image--036.jpg%3Falt%3Dmedia%26token%3Dbcf3e359-7ed7-4319-b9d2-7b47b0eaad05&width=768&dpr=3&quality=100&sign=ecc6780f&sv=2) [PreviousResourceschevron-left](https://mirror-networking.gitbook.io/docs/community-guides/resources) [NextUnity for MMORPGschevron-right](https://mirror-networking.gitbook.io/docs/community-guides/unity-for-mmorpgs) Last updated 3 years ago * [Part 1](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-1) * [Part 2](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-2) * [Part 3](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-3) * [Part 4](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-4) * [Part 5](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-5) * [Part 6](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-6) * [Part 7](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-7) * [Part 8](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-8) * [Part 9](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-9) * [Part 10](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-10) * [Part 11](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-11) * [Part 12](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-12) * [Part 13](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-13) * [Part 14](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-14) * [Part 15](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-15) * [Part 16](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-16) * [Part 17](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-17) * [Part 18](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-18) * [Part 19](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-19) * [Part 20](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-20) * [Part 21](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-21) * [Part 22](https://mirror-networking.gitbook.io/docs/community-guides/quick-start-guide#part-22) Copy using Mirror; using UnityEngine; namespace QuickStart { public class PlayerScript : NetworkBehaviour { public override void OnStartLocalPlayer() { Camera.main.transform.SetParent(transform); Camera.main.transform.localPosition = new Vector3(0, 0, 0); } void Update() { if (!isLocalPlayer) { return; } float moveX = Input.GetAxis("Horizontal") * Time.deltaTime * 110.0f; float moveZ = Input.GetAxis("Vertical") * Time.deltaTime * 4f; transform.Rotate(0, moveX, 0); transform.Translate(0, 0, moveZ); } } } Copy using Mirror; using UnityEngine; namespace QuickStart { public class PlayerScript : NetworkBehaviour { public TextMesh playerNameText; public GameObject floatingInfo; private Material playerMaterialClone; [SyncVar(hook = nameof(OnNameChanged))] public string playerName; [SyncVar(hook = nameof(OnColorChanged))] public Color playerColor = Color.white; void OnNameChanged(string _Old, string _New) { playerNameText.text = playerName; } void OnColorChanged(Color _Old, Color _New) { playerNameText.color = _New; playerMaterialClone = new Material(GetComponent().material); playerMaterialClone.color = _New; GetComponent().material = playerMaterialClone; } public override void OnStartLocalPlayer() { Camera.main.transform.SetParent(transform); Camera.main.transform.localPosition = new Vector3(0, 0, 0); floatingInfo.transform.localPosition = new Vector3(0, -0.3f, 0.6f); floatingInfo.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); string name = "Player" + Random.Range(100, 999); Color color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f)); CmdSetupPlayer(name, color); } [Command] public void CmdSetupPlayer(string _name, Color _col) { // player info sent to server, then server updates sync vars which handles it on all clients playerName = _name; playerColor = _col; } void Update() { if (!isLocalPlayer) { // make non-local players run this floatingInfo.transform.LookAt(Camera.main.transform); return; } float moveX = Input.GetAxis("Horizontal") * Time.deltaTime * 110.0f; float moveZ = Input.GetAxis("Vertical") * Time.deltaTime * 4f; transform.Rotate(0, moveX, 0); transform.Translate(0, 0, moveZ); } } } Copy private SceneScript sceneScript; void Awake() { //allow all players to run this sceneScript = GameObject.FindObjectOfType(); } [Command] public void CmdSendPlayerMessage() { if (sceneScript) sceneScript.statusText = $"{playerName} says hello {Random.Range(10, 99)}"; } [Command] public void CmdSetupPlayer(string _name, Color _col) { //player info sent to server, then server updates sync vars which handles it on all clients playerName = _name; playerColor = _col; sceneScript.statusText = $"{playerName} joined."; } public override void OnStartLocalPlayer() { sceneScript.playerScript = this; //. . . . ^ new line to add here Copy using Mirror; using UnityEngine; using UnityEngine.UI; namespace QuickStart { public class SceneScript : NetworkBehaviour { public Text canvasStatusText; public PlayerScript playerScript; [SyncVar(hook = nameof(OnStatusTextChanged))] public string statusText; void OnStatusTextChanged(string _Old, string _New) { //called from sync var hook, to update info on screen for all players canvasStatusText.text = statusText; } public void ButtonSendMessage() { if (playerScript != null) playerScript.CmdSendPlayerMessage(); } } } Copy private int selectedWeaponLocal = 1; public GameObject[] weaponArray; [SyncVar(hook = nameof(OnWeaponChanged))] public int activeWeaponSynced = 1; void OnWeaponChanged(int _Old, int _New) { // disable old weapon // in range and not null if (0 < _Old && _Old < weaponArray.Length && weaponArray[_Old] != null) weaponArray[_Old].SetActive(false); // enable new weapon // in range and not null if (0 < _New && _New < weaponArray.Length && weaponArray[_New] != null) weaponArray[_New].SetActive(true); } [Command] public void CmdChangeActiveWeapon(int newIndex) { activeWeaponSynced = newIndex; } void Awake() { // disable all weapons foreach (var item in weaponArray) if (item != null) item.SetActive(false); } Copy void Update() { if (!isLocalPlayer) { // make non-local players run this floatingInfo.transform.LookAt(Camera.main.transform); return; } float moveX = Input.GetAxis("Horizontal") * Time.deltaTime * 110.0f; float moveZ = Input.GetAxis("Vertical") * Time.deltaTime * 4f; transform.Rotate(0, moveX, 0); transform.Translate(0, 0, moveZ); if (Input.GetButtonDown("Fire2")) //Fire2 is mouse 2nd click and left alt { selectedWeaponLocal += 1; if (selectedWeaponLocal > weaponArray.Length) selectedWeaponLocal = 1; CmdChangeActiveWeapon(selectedWeaponLocal); } } Copy using UnityEngine; namespace QuickStart { public class SceneReference : MonoBehaviour { public SceneScript sceneScript; } } Copy public SceneReference sceneReference; Copy void Awake() { //allows all players to run this sceneScript = GameObject.Find(“SceneReference”).GetComponent().sceneScript; } Copy public void ButtonChangeScene() { if (isServer) { Scene scene = SceneManager.GetActiveScene(); if (scene.name == "MyScene") NetworkManager.singleton.ServerChangeScene("MyOtherScene"); else NetworkManager.singleton.ServerChangeScene("MyScene"); } else Debug.Log("You are not Host."); } Copy using UnityEngine; using UnityEngine.SceneManagement; namespace QuickStart { public class Menu : MonoBehaviour { public void LoadScene() { SceneManager.LoadScene("GamesList"); } } } Copy using UnityEngine; using UnityEngine.SceneManagement; namespace QuickStart { public class GamesList : MonoBehaviour { public void LoadScene() { SceneManager.LoadScene("Menu"); } } } Copy using UnityEngine; namespace QuickStart { public class Weapon : MonoBehaviour { public float weaponSpeed = 15.0f; public float weaponLife = 3.0f; public float weaponCooldown = 1.0f; public int weaponAmmo = 15; public GameObject weaponBullet; public Transform weaponFirePosition; } } Copy public Text canvasAmmoText; public void UIAmmo(int _value) { canvasAmmoText.text = "Ammo: " + _value; } Copy private Weapon activeWeapon; private float weaponCooldownTime; Copy void OnWeaponChanged(int _Old, int _New) { // disable old weapon // in range and not null if (0 < _Old && _Old < weaponArray.Length && weaponArray[_Old] != null) weaponArray[_Old].SetActive(false); // enable new weapon // in range and not null if (0 < _New && _New < weaponArray.Length && weaponArray[_New] != null) { weaponArray[_New].SetActive(true); activeWeapon = weaponArray[activeWeaponSynced].GetComponent(); if (isLocalPlayer) sceneScript.UIAmmo(activeWeapon.weaponAmmo); } } Copy if (selectedWeaponLocal < weaponArray.Length && weaponArray[selectedWeaponLocal] != null) { activeWeapon = weaponArray[selectedWeaponLocal].GetComponent(); sceneScript.UIAmmo(activeWeapon.weaponAmmo); } Copy if (Input.GetButtonDown("Fire1") ) //Fire1 is mouse 1st click { if (activeWeapon && Time.time > weaponCooldownTime && activeWeapon.weaponAmmo > 0) { weaponCooldownTime = Time.time + activeWeapon.weaponCooldown; activeWeapon.weaponAmmo -= 1; sceneScript.UIAmmo(activeWeapon.weaponAmmo); CmdShootRay(); } } Copy [Command] void CmdShootRay() { RpcFireWeapon(); } [ClientRpc] void RpcFireWeapon() { //bulletAudio.Play(); muzzleflash etc GameObject bullet = Instantiate(activeWeapon.weaponBullet, activeWeapon.weaponFirePosition.position, activeWeapon.weaponFirePosition.rotation); bullet.GetComponent().velocity = bullet.transform.forward * activeWeapon.weaponSpeed; Destroy(bullet, activeWeapon.weaponLife); } --- # SyncDictionary | Mirror A SyncDictionary is an associative array containing an unordered list of key, value pairs. Keys and values can be any [supported mirror type](https://mirror-networking.gitbook.io/docs/manual/guides/data-types) . By default we use .Net [Dictionaryarrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?view=netcore-3.1) which may impose additional constraints on the keys and values. SyncDictionary works much like [SyncLists](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) : when you make a change on the server the change is propagated to all clients and the appropriate Actions are invoked. Only deltas are transmitted. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary#usage) Usage ------------------------------------------------------------------------------------------------------------------ circle-info `SyncDictionary must` be declared **readonly** and initialized in the constructor. circle-exclamation Note that by the time you wire up the Action handlers, the dictionary will already be initialized, so they will not get invoked for the initial data, only updates. [hashtag](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary#simple-example) Simple Example ------------------------------------------------------------------------------------------------------------------------------------ Copy using System.Collections.Generic; using UnityEngine; using Mirror; public enum Slots : byte { head, body, feet, hands } public struct Item { public string name; public int hitPoints; public int durability; public Item(string name, int hitPoints, int durability) { this.name = name; this.hitPoints = hitPoints; this.durability = durability; } public override string ToString() { return $"name={name} hitPoints={hitPoints} durability={durability}"; } } public class SyncDictionaryExample : NetworkBehaviour { public readonly SyncDictionary Equipment = new SyncDictionary(); public override void OnStartServer() { Equipment[Slots.head] = new Item("Helmet", 10, 20); Equipment[Slots.body] = new Item("Epic Armor", 50, 50); Equipment[Slots.feet] = new Item("Sneakers", 3, 40); Equipment[Slots.hands] = new Item("Sword", 30, 15); } public override void OnStartClient() { // Add handlers for SyncDictionary Actions Equipment.OnAdd += OnItemAdded; Equipment.OnSet += OnItemChanged; Equipment.OnRemove += OnItemRemoved; Equipment.OnClear += OnDictionaryCleared; // OnChange is a catch-all event that is called for any change // to the dictionary. It is called after the specific events above. // Strongly recommended to use the specific events above instead! Equipment.OnChange += OnDictionaryChanged; // Dictionary is populated before handlers are wired up so we // need to manually invoke OnAdd for each element. foreach (Slots key in Equipment.Keys) Equipment.OnAdd.Invoke(key); } public override void OnStopClient() { // Remove handlers when client stops Equipment.OnAdd -= OnItemAdded; Equipment.OnSet -= OnItemChanged; Equipment.OnRemove -= OnItemRemoved; Equipment.OnClear -= OnDictionaryCleared; Equipment.OnChange -= OnDictionaryChanged; } void OnItemAdded(Slots key) { Debug.Log($"Element added {key} {Equipment[key]}"); } void OnItemChanged(Slots key, Item oldValue) { Debug.Log($"Element changed {key} from {oldValue} to {Equipment[key]}"); } void OnItemRemoved(Slots key, Item oldValue) { Debug.Log($"Element removed {key} {oldValue}"); } void OnDictionaryCleared() { // OnDictionaryCleared is called before the dictionary is actually cleared // so we can iterate the dictionary to get the elements if needed. foreach (KeyValuePair kvp in Equipment) Debug.Log($"Element cleared {kvp.Key} {kvp.Value}"); } // OnDictionaryChanged is a catch-all event that is called for any change // to the dictionary. It is called after the specific events above. // // NOTE: It's strongly recommended to use the specific events above instead! // // For OP_ADD, the value param is the NEW entry. // For OP_SET, the value param is the OLD entry. // For OP_REMOVE, the value param is the OLD entry. // For OP_CLEAR, the value param is null / default. void OnDictionaryChanged(SyncDictionary.Operation op, Slots key, Item value) { switch (op) { case SyncDictionary.Operation.OP_ADD: // value is the new entry Debug.Log($"Element added {key} {value}"); break; case SyncDictionary.Operation.OP_SET: // value is the old entry Debug.Log($"Element set {key} from {value} to {Equipment[key]}"); break; case SyncDictionary.Operation.OP_REMOVE: // value is the old entry Debug.Log($"Element removed {key} {value}"); break; case SyncDictionary.Operation.OP_CLEAR: // value is null / default // we can iterate the dictionary to get the elements if needed. foreach (KeyValuePair kvp in Equipment) Debug.Log($"Element cleared {kvp.Key} {kvp.Value}"); break; } } } By default, SyncDictionary uses a [Dictionaryarrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?view=netcore-3.1) to store it's data. If you want to use a different `IDictionary` implementation such as [SortedListarrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.collections.sortedlist?view=netcore-3.1) or [SortedDictionaryarrow-up-right](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.sorteddictionary-2?view=netcore-3.1) , then use `SyncIDictionary` and pass the dictionary instance you want it to use. For example: [PreviousSyncListschevron-left](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synclists) [NextSyncHashSetchevron-right](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/synchashset) Last updated 1 year ago * [Usage](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary#usage) * [Simple Example](https://mirror-networking.gitbook.io/docs/manual/guides/synchronization/syncdictionary#simple-example) Copy public class ExamplePlayer : NetworkBehaviour { public readonly SyncIDictionary Equipment = new SyncIDictionary(new SortedList()); } ---