Top Banner
Unity and WebSockets Adventures in Mobile Games Josh Glover Lead Backend Developer
28

Unity and WebSockets

Aug 08, 2015

Download

Documents

Josh Glover
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Unity and WebSockets

Unity and WebSocketsAdventures in Mobile

Games

Josh GloverLead Backend Developer

Page 2: Unity and WebSockets

Rock Science 2

Page 3: Unity and WebSockets

What’s a WebSocket?

● Bidirectional TCP connection● Initiated from an HTTP connection by

sending Upgrade header

GET /chat HTTP/1.1Host: server.example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13Origin: http://example.com

HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: HSmrc0sMlYU=Sec-WebSocket-Protocol: chat

Page 4: Unity and WebSockets

Why WebSockets?

● Server can push messages instead of being polled

● Polling often leads to large percentage of request load being worthless

● Client disconnection can be part of API

Page 5: Unity and WebSockets

Why not WebSockets?

● Servers can’t be purely stateless● How does a client on server A interact with a

client on server B?● What happens when a server crashes?● What if a client has a spotty network

connection?

Page 6: Unity and WebSockets

Mix and match

● Use WebSockets where remote push is a killer app

● Use plain old REST for everything else● Gracefully degrade from WebSockets to

REST when network connectivity is poor● HTTP Kit is a perfect fit!

Page 7: Unity and WebSockets

● Open source C# WebSockets clienthttps://github.com/sta/websocket-sharp/

● Available on the Unity Asset Storehttps://www.assetstore.unity3d.com/en/#!/content/8959

● With Unity 5, drop in your Assets folder and compile away (full .NET 2.0 API only)

Page 8: Unity and WebSockets

Connectingusing WebSocketSharp;

var ws = new WebSocket("ws://echo.websocket.org");

// We'll get to this

ws.OnOpen += OnOpenHandler;

ws.OnMessage += OnMessageHandler;

ws.OnClose += OnCloseHandler;

ws.OnError += OnErrorHandler;

ws.ConnectAsync();

Page 9: Unity and WebSockets

private void OnOpenHandler(object sender, System.EventArgs e) {

Debug.Log("WebSocket connected!");

// Here is where you do useful stuff

}

How do I know when I’m connected?

Page 10: Unity and WebSockets

private void OnSendComplete(bool success) {

Debug.Log("Message sent successfully? " + success);

}

ws.SendAsync("This WebSockets stuff is a breeze!", OnSendComplete);

Sending a message

Page 11: Unity and WebSockets

private void OnMessageHandler(object sender, MessageEventArgs e) {

Debug.Log("WebSocket server said: " + e.Data);

}

Receiving a message

Page 12: Unity and WebSockets

private void OnCloseHandler(object sender, CloseEventArgs e) {

Debug.Log("WebSocket closed with reason: " + e.Reason);

}

ws.CloseAsync();

Disconnecting

Page 13: Unity and WebSockets

Live Demo!

Page 14: Unity and WebSockets

But wait, asynchronous means...

THREADS!

Page 15: Unity and WebSockets

Unity threading model

● Single-threaded with coroutines● API generally not thread-safe● Anything that updates the screen must

happen on the main thread

Page 16: Unity and WebSockets

websocket-sharp threading model

● .NET threads● Anything done asynchronously happens on

a background thread● Event handlers (OnOpen, OnMessage, etc.)

are invoked on background threads

Page 17: Unity and WebSockets

And never the twain shall meet?

● This would be a (more) boring talk● Enter our old Computer Science buddy, the

Finite State Machine

Page 18: Unity and WebSockets

A simple state machineusing UnityEngine;

public enum State { NotRunning, Running, Connected, Ping, Pong, Done }

public delegate void Handler();

public class StateMachine : MonoBehaviour {

public void Run() { … }

public void Transition(State state) { … }

public void AddHandler(State state, Handler handler) { … }

public void Update() { … }

}

Page 19: Unity and WebSockets

using System.Collections.Generic;

public class StateMachine : MonoBehaviour {

private readonly object syncLock = new object();

private readonly Queue<State> pending = new Queue<State>();

public void Transition(State state) {

lock(syncLock) {

pending.Enqueue(state);

}

}

}

Requesting transitions

Page 20: Unity and WebSockets

public class StateMachine : MonoBehaviour {

private readonly Dictionary<State, Handler> handlers

= new Dictionary<State, Handler>();

public void AddHandler(State state, Handler handler) {

handlers.Add(state, handler);

}

}

Transition handlers

Page 21: Unity and WebSockets

Handling transitionspublic class StateMachine : MonoBehaviour {

public void Update() {

while (pending.Count > 0) {

currentState = pending.Dequeue();

Handler handler;

if (handlers.TryGetValue(currentState, out handler)) {

handler();

}

}

}

}

Page 22: Unity and WebSockets

Start me up!public class StateMachine : MonoBehaviour {

private State currentState = State.NotRunning;

public void Run() {

Transition(State.Running);

}

}

Page 23: Unity and WebSockets

Putting it all together (1)using UnityEngine;

using WebSocketSharp;

public class StatefulMain : MonoBehaviour {

public StateMachine stateMachine;

private WebSocket ws;

void Start() {

ws = new WebSocket("ws://echo.websocket.org");

ws.OnOpen += OnOpenHandler;

ws.OnMessage += OnMessageHandler;

ws.OnClose += OnCloseHandler;

Page 24: Unity and WebSockets

Putting it all together (2) stateMachine.AddHandler(State.Running, () => {

ws.ConnectAsync();

});

stateMachine.AddHandler(State.Connected, () => {

stateMachine.Transition(State.Ping);

});

stateMachine.AddHandler(State.Ping, () => {

ws.SendAsync("This WebSockets stuff is a breeze!", OnSendComplete);

});

stateMachine.AddHandler(State.Pong, () => {

ws.CloseAsync();

});

Page 25: Unity and WebSockets

private void OnOpenHandler(object sender, System.EventArgs e) {

Debug.Log("WebSocket connected!");

stateMachine.Transition(State.Connected);

}

private void OnMessageHandler(object sender, MessageEventArgs e) {

Debug.Log("WebSocket server said: " + e.Data);

stateMachine.Transition(State.Pong);

}

private void OnCloseHandler(object sender, CloseEventArgs e) {

Debug.Log("WebSocket closed with reason: " + e.Reason);

stateMachine.Transition(State.Done);

}

Putting it all together (3)

Page 26: Unity and WebSockets

Putting it all together (4) void Start() {

// WebSocket init code from previous slides

// State machine handlers from previous slides

stateMachine.Run();

}

Page 27: Unity and WebSockets

Live Demo!

Page 28: Unity and WebSockets

Use the Source, Luke

https://github.com/jmglov/unity-ws-demo