What is the Purpose of this DOTS Tutorial?

This is a sample project that demonstrates how to create a multiplayer AR experience using Unity's DOTS. We include full workflows, code, GIFs and also share links to external resources.
Finished Project - Shooting down AR player from desktop
Finished Project - Getting shot down by desktop player

Purpose

At Moetsi we build Reality Modeling technologies for Mixed Reality experiences. By Reality Modeling we mean the process of: capturing the spatial map of a real space, modeling the state of the environment, the objects within it, and the positioning of the sensors, and then packaging all that data for end-users.

A lot of our use-cases require both desktop and "live" (AR) client networking because part of what our technology does is stream updated Reality Models in real-time to connected clients, which is data-intensive.

We choose Unity DOTS and DOTS NetCode for our interaction layer. DOTS is able to handle heavy data processing without draining device batteries. DOTS NetCode uses an authoritative server model that works best for Reality Modeling.

Unity DOTS is still in the beginning of its development and as such, it goes through major iterations. Sometimes there are breaking changes in newly released versions of DOTS. We know this is frustrating, so to help out the developer community, the Moetsi team does its very best to keep up with DOTS' evolution and its interdependencies across Unity's technology stack. There are not too many DOTS tutorial resources online, which means there are probably a lot of developers going through the same (painful) process of trying to figure it all out. Resources on how to connect GameObject (Monobehaviour) Unity and ECS Unity (hybrid development) seems to be especially lacking for things like UI Toolkit and UI Builder. Hopefully Moetsi fills a void for you and the rest of the dev community!

We provide a tutorial and sample project for how to create a multiplayer real-time XR experience using Unity's DOTS. Anyone that has been interested in trying out DOTS but are concerned about stability or package interoperability can use this tutorial knowing that "it will work."

In this gitbook, we build a project that can deploy to both desktop and ARKit platforms. Desktop players will be able to navigate using WASD keys and AR players will be able to navigate using their device movement.

Navigating between scenes using UI and appropriately handling creating/destroying client/server worlds

Github repo: https://github.com/moetsi/Unity-DOTS-Multiplayer-XR-Sample

Our focus here is on how to put pieces together in Unity DOTS, not an explanation of what the pieces are. For in-depth explanations of "what" the technologies are, we provide links to great external resources throughout this gitbook; we encourage you to click on those to dive in and learn more!

The styling (GUI) in the builds of this sample project is very minimal on purpose. Our sample project is not meant to provide a how-to guide on how to make a juicy game because we do not want to cloud your understanding of the underlying architecture. That's why we exclude anything but basic example implementations. If you are underwhelmed by the styling of the Asteroids apps in this project, that is good. A lot of the other DOTS tutorial materials we found online added superfluous bells and whistles that made projects more interesting, but we found that they got in the way of our true understanding of the underlying architecture.

Code-alongs will take anywhere from 5 to 50 hours (depending on your skill level and time commitment to reading through each line) and they cover these Unity packages:

Entities
Physics
Netcode
UI B/TK
Multi
AR Found
Entities

Entities v0.17

  • Sub Scenes and conversions

    • Setting components and variables during conversion

  • Using EntityManager to make structural changes

  • Using command buffers to make structural entity changes

    • Setting up command buffers to run parallel jobs with CreateCommandBuffer().AsParallelWriter()

  • Adding, setting, and removing components

  • Generating authoring components and IConvertGameObjectToEntity interfaces

  • Entity queries and .ForEach()

    • Setting local variables for entity queries

    • Scheduling a job with .Schedule()

    • Scheduling a parallel job with .ScheduleParallel()

    • Running on the main thread with .Run()

    • Combining job handles with JobHandle.CombineDependencies()

  • Create and destroy entities programmatically

  • Create and move entities based on user input

  • Create an entity from a prefab

    • Adding cameras to entities

  • Hybrid ECS

  • New Build Configuration system

    • Creating a base shared configuration

  • Sub-second "play" start

Physics

Physics v0.6

  • Unity DOTS Physics

    • Using FixedStepSimulationGroup for custom systems

  • Physics Body

    • Adjusting PhysicsVelocity programmatically

  • Physics Shape

    • Updating shape type to prefab

  • Physics Categories

    • Custom categories for collisions and interactions

  • Triggers on collisions

    • Changing stateless triggers to buffer of stateful triggers

  • Acting on triggers to change materials and destroy entities

Netcode

NetCode v0.6

  • Navigating multiple ECS Worlds

  • Creating a ECS NetworkConnectionEntity (NCE) on the client and server

    • Creating a socket connection using NetworkStreamReceiveSystem

    • Use GhostDistanceImportance component

  • Sending RPCs between server and client

    • Sending data with RPCs

    • Using InvokeExecute on receiving NCE to make updates

  • Loading a game on the client

    • Using NetworkStreamInGame component

  • Updating the CommandTargetComponent on a NetworkConnectionEntity

    • Setting targetEntity field to ICommandData buffer

  • Creating networked entities ("Ghosts")

    • Ghost Authoring Component

      • Updating Supported Ghost Modes

  • Server-spawned entities

  • Sending client inputs with ICommandData

    • Predicted responses to ICommandData by using ClientSimulationSystemGroup.ServerTick

  • Responding to ICommandData on both the client and server using GhostPredictionSystemGroup.ShouldPredict()

  • Client-predicted entities and predicted-spawned entities

    • Adding PredictedGhostSpawnRequestComponent

  • Ghost classification systems

    • Traversing GhostSpawnBuffer to locate predicted spawn entity

  • Proper NetCode entity destruction

    • Server-side destruction

    • Using ISystemStateComponent component as a call back to clean up destroyed players

UI B/TK

UI Builder v1.0 and UI Toolkit v1.0

  • Creating a UI document and Panel settings

  • Creating a ScreenManager to handle switching between views

  • Nesting uxmls and custom Visual Elements in UI Builder

  • Creating custom VisualElements

    • Setting callbacks on OnGeometryChange()

    • Updating DisplayStyle to switch views

  • Creating a USS document shared by multiple UXML files

    • Creating a class list

    • Extracting inline styles to a class list

    • Adding classes to elements from StyleSheets

    • Creating custom styling for :hover and :active states

  • Styling a view to be responsive to changes in width to be prepared for both mobile and desktop views

    • Creating headers and footers for game information

    • Using display flex in UI builder to create responsive designs

    • Using standard Unity elements to create an interface

      • VisualElement

      • Label

      • TextField

      • Button

    • Adding a png or SVG background

  • Creating a ListView

    • Setting a source of data for the ListView

    • Creating custom click events and loading data when clicking on an item in ListView

  • Loading data in between scenes to configure host/client build

    • Using launch GameObjects to configure a scene to build as a host or a client

  • Creating a ClientServerBootstrap to stop automatic world creation

    • Triggering client and server worlds manually

    • Supporting Thin Clients when creating client worlds

  • Deleting all entities and worlds

    • Using UniversalQuery in EntityManager

    • Clean up to return to initial state

Multi

NetCode v0.6, UDP Client, Broadcasting, Threads, Graceful exits

  • Using launch GameObjects to configure server and client connections

    • Triggering starting a game as a NetCode host

    • Triggering starting a game joining as a NetCode client to a specific IP address

  • Sending and receiving broadcast messages

    • Automatically sending a broadcast UDP packet of game information including IP address on LAN for players to join

    • Listening and receiving broadcast UDP packet information and populating a ListView of available LAN games

  • Running Threads for listening for UDP packets

    • Being able to run non-Unity handled threads in-game

  • Graceful handling of joining and leaving games

    • Adding NetworkStreamRequestDisconnect component on both host and client when quitting a game

    • Handling timeouts by querying for NetworkStreamDisconnected components from host and client to clean up entities and return to title screen

  • Server-authoritative score keeping

    • Creating PlayerScore ghosts and HighestScore ghosts to keep player scores authoritative and in sync

    • Associating scores with NCE NetworkIdComponent values

  • UI Toolkit + DOTS

    • Updating Game UI through a MonoBehaviour by pulling DOTS data from ghosts

  • Using GhostRelevancyMode to be mindful of network transmission

    • We will implement a server-side system that will send only send ghosts within a certain radius to players

    • We will also include overriding this behavior to send player scores to all players

AR Found

AR Foundation v4.1.3

  • Setting up AR Foundation + ARKit plug-in

  • Adding AR Foundation GameObjects to game

    • AR Session Origin

    • AR Session

  • Dynamically checking if deployed to AR platform and disabling AR functionality if not

    • Creating AR-specific systems that only run when AR enabled

  • Grabbing Pose Driver value and providing it to ECS to move player

    • Updating input response systems for updated movement controls

  • Pulling ECS data spawn position and updating Pose Driver to move location of AR Camera to behind player

    • Use ARSessionOrigin.MakeContentAppearAt() to update origin of AR session based on game play

  • Dynamically updating UI for AR instructions when deployed to AR platform

  • Updating PanelSettings to be responsive to both desktop and mobile platforms

The UI Builder and UI Toolkit sections can be useful as standalone. However, all of the other sections build off one another so it is best to go page-by-page.

At Moetsi, we will always update our sample project to stay current with the latest set of working Unity packages.

Case in Point: in the middle of us writing this gitbook, DOTS was upgraded mid-project and we adjusted course to update our documentation and all of the packages as soon as possible.

This Sample Project is intended for developers who:

✅ already have a general understanding of Unity

✅ are looking for info on Entity, Jobs, Physics, NetCode, UI Builder, UI Toolkit, Multiplayer and AR Foundation packages

✅ are looking for a stable Monobehaviour / ECS hybrid solution template that is kept up to date with new releases

✅ are interested in building apps and/or experiences with high number of components/performance requirements (very often these are AR or other mixed reality apps, but don't need to be!)

This is NOT intended for those who:

❌ are looking for a full introduction to software development

❌ are looking for a "Pure ECS" solution

❌ are looking for a framework