Developer Documentation

Basic Concepts

ODIN is a client server platform. Servers are hosted by 4Players, but can also be hosted by clients. The whole system is stateless and scalable. There are no databases keeping track of everything, instead everything just relies on stateless connections and some tokens that are used during authentication.

Info

In the following diagrams we use these words frequently.

Local
For the local client (i.e. you as a developer testing your current build)
Server
The ODIN server hosted by 4Players or hosted by yourself on your own infrastructure or the cloud
Remote
All other clients connected to the same server/room, i.e. your colleagues.

Topology

This diagram outlines the basic structure of two clients connected to an ODIN server. Client 1 has joined two rooms listening and talking and Client 2 has also joined room 2 but is just listening there.

graph TB;
    subgraph ODIN Server
        Connection1[Connection 1]
        Connection2[Connection 2]
    end
    Client1[Client 1] -- Authenticate --> Connection1
    Client2[Client 2] -- Authenticate --> Connection2
    subgraph Room1[Room 1]
        Peer11[Peer 1] -- StartMedia --> MediaStream111[Media Stream 1]
    end
    subgraph Room2[Room 2]
        Peer21[Peer 1] -- StartMedia --> MediaStream211[Media Stream 1]
        Peer21[Peer 1] -- StartMedia --> MediaStream212[Media Stream 2]
        Peer22[Peer 2]
    end    
    Connection1 -- JoinRoom --> Peer11
    Connection1 -- JoinRoom --> Peer21
    Connection2 -- JoinRoom --> Peer22    

Every client connects an ODIN server and authenticates with an access token and joins a room. Once the client has joined a room, he is a peer inside the ODIN room. Every peer can add media to that room, linked to a physical device like a microphone. Clients can join multiple rooms at the same time and can add multiple media streams at the same time.

Important

ODIN rooms work independently of each other. This means that each client is a different peer in every room, having a different peer id. Also, you cannot use the same media stream for multiple rooms at once, but you have to create a new one for each room.

Info

Every peer receives the media streams of the other peers connected to the same room, but are not required to add their own media. Spectators will want to listen but not talking themselves. A muted peer for example also does not have a media.

Connecting to Server

The first step is to connect to a server and a room. If you are using one of our high level SDKs like Unity or Unreal joining a room is all you have to do. The SDK handles authentication and server connection for you.

sequenceDiagram

participant Local
participant Server
participant Remote

Local ->>+ Server: Authenticate
Server -->>- Local: Success

Local ->>+ Server: JoinRoom
Server ->> Remote: PeerJoined
Server -->>- Local: Success

Local --> Server: Opening Room Stream
Server ->> Local: Joined

Once the connection is established and the room has joined an event is sent to all other peers in the same room: PeerJoined. This allows you to update your UI for example like showing a list of peers that are within a room.

The client who joined the room will receive a RoomJoin and RoomJoined event. If a user clicks a button to join a room, you can use the RoomJoin event to start showing a loading indicator and hiding it once RoomJoined has been triggered.

Event summary

LocalRemoteDescription
OnRoomJoin Triggered if user started to join a room
OnRoomJoined OnPeerJoined Triggered if user joined a room

ODIN does not require any bookkeeping. A room is created automatically for the first connection and will be removed whenever the last user left the room. You join a room by calling the JoinRoom method of the OdinHandler instance in your scene.

class MyVoiceHandler: MonoBehaviour
{
  public string RoomName = "default";
  
  // Start is called before the first frame update
  void Start()
  {
    OdinHandler.Instance.JoinRoom(RoomName);
  }
}
LocalRemoteDescription
On Room Joined On Peer Joined Triggered if user joined a room

ODIN does not require any bookkeeping. A room is created automatically for the first connection and will be removed whenever the last user left the room. You join a room by calling the Join Room function in your blueprint.

Info

Please note: To join a room you need to create an access token. The whole process is described in the Unreal Engine Manual.

Joining a room looks like this:

Joining a room

Joining a room

Event handling looks like this:

The wired up peer joined event handler

The wired up peer joined event handler

Starting a media

As defined above, every peer connected to a room can (but does not have to) add a media, i.e. a stream connected to the peers’ input device, e.g. a microphone. Please note: Every peer can add multiple media to the same room (i.e. audio and video). In Contrary, you can not use the same media twice, e.g. for 2 different rooms.

sequenceDiagram

participant Local
participant Server
participant Remote

Local ->>+ Server: AddMedia
Server ->> Remote: MediaAdded
Server -->>- Local: Success

The local OdinHandler will trigger OnCreatedMediaObject once the request media has been added to the server. OnMediaAdded is triggered for media added by other peers to the room.

Event summary

LocalRemoteDescription
OnCreatedMediaObject OnMediaAdded Triggered once the media has been added to the room on the server
Info

It’s important to handle the OnMediaAdded callbacks. Whenever you receive this event, you need to call the AddPlaybackComponent method on your OdinHandler instance which will create a PlaybackComponent and assign to a GameObject that corresponds to this peer in Odin.

LocalRemoteDescription
On Add Media To Room Success On Media Added Triggered once the media has been added to the room on the server
Info

It’s important to handle the On Media Added event. Whenever you receive this event, you need to assign the media to an Odin Synth Component that is either part of the asset (added at design time) or you can also create that component with Add Odin Synth Component in your blueprint. The Odin Synth Component generates audio output from the incoming media stream.

Adding a media looks like this:

Handling On Media Added events

Handling On Media Added events

Stopping a media

Users can mute their audio streams, in this case, the media stream should be stopped, so that no data is captured and to ODIN servers. Of course, also leaving a room can lead to stopped media.

sequenceDiagram

participant Local
participant Server
participant Remote

Local ->>+ Server: StopMedia
Server ->> Remote: MediaStopped
Server -->>- Local: Success

The MediaStopped event will be triggered once the request media has been deleted on the server.

Event summary

LocalRemoteDescription
OnDeleteMediaObject OnMediaRemoved Triggered once the media has been added to the room on the server
Info

It’s important to handle the OnMediaRemoved callbacks as it’s up to you to remove the PlaybackComponent from the corresponding GameObject that you used initially when adding the PlaybackComponent in the OnMediaAdded callback.

Updating Peer User Data

Every peer in Unity can store arbitrary information as user data. When local user data is updated, the server updates user data at all clients and sends this message. Read more about user data in our guide: Understanding User Data.

sequenceDiagram

participant Local
participant Server
participant Remote

Local ->>+ Server: UpdateUserData
Server ->> Remote: PeerUpdated
Server -->>- Local: Success

Whenever a peer updates his data, all other peers receive the PeerUpdated event to handle the new data.

Event summary

LocalRemoteDescription
OnPeerUserDataChanged OnPeerUserDataChanged Triggered once for every updated peer user data

Sending Arbitrary Data

You can use ODIN to send arbitrary data to other clients. You can use this method to build simple multiplayer games that don’t require complex, real-time movement. For many casual games or board games, this message is enough to sync the players positions and other information of the game state with all clients.

The data you can send is basically just an array of bytes. You can use any data serialization that makes sense to you. Many game engines already provide data serialization features.

Warning

Note: You will only receive the MessageReceived event if your own peer ID was in the list of recipients.

sequenceDiagram

participant Local
participant Server
participant Remote

Local ->>+ Server: SendMessage
Server ->> Remote: MessageReceived
Server -->>- Local: Success

Event Summary

LocalRemoteDescription
OnMessageReceived OnMessageReceived Triggered after receiving a message

Disconnecting

If peers disconnect other peers will be notified with the PeerLeft events.

sequenceDiagram

participant Local
participant Server
participant Remote

Local -->+ Server: Closing Connection
Server ->> Remote: PeerLeft
deactivate Server

Event Summary

LocalRemoteDescription
OnRoomLeave Triggered if user started to leave a room
OnRoomLeft OnPeerLeft Triggered if user left a room

Getting Kicked

If a peer is kicked from the server, this message flow will take place:

sequenceDiagram

participant Local
participant Server
participant Remote

activate Server
Server ->> Local: Left
Server ->> Remote: PeerLeft
Server --> Local: Closing Connection
deactivate Server

Event Summary

LocalRemoteDescription
OnRoomLeft OnPeerLeft Triggered if user has been kicked from a room
LocalRemoteDescription
-On Peer Left Triggered if user left a room

Next Steps

Curious enough? Then get started with our Getting Started Guides. Choose your platform and start coding. It’ll only take 20 minutes to play around with ODIN right in your game engines editor: Getting Started.

Getting Started with ODIN

Still not convinced or wanting to learn more? We have compiled a couple of use cases and how ODIN is best suited to handle them perfectely, being it a First Person Shooter or a MMO Battle Royal Game.

Next: Use Cases