- Cubeがクリックされたことを検知
- HTTPリクエスト(GET)でJSONの取得
- HTTPリクエスト(POST)でJSONの送信
- WebSocketによる通信 👈 今回はここ
今回のモックを作りたくて色々と記事を書いてきましたが、直接関係あるのは初回の記事だけで、Networking.UnityWebRequestを使ったGET・POSTは飛ばしても大丈夫です。
WebSocketは、websocket-sharpを使って実現します。
websocket-sharpの準備
websocket-sharpをダウンロードし、解凍します。
websocket-sharp.slnをダブルクリックし、Visual Studioで開きます。
Example、Example2、Example3を削除します。
リリースビルドに切り替え、ビルドすると、websocket-sharp/bin/Release/websocket-sharp.dllが生成されます。
Unityの修正
websocket-sharp.dllの読み込み
Assets/Plugins以下に、websocket-sharp.dllを設置します。
スクリプトの差し替え
Assets/Scripts/WebSocketClient.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using WebSocketSharp; public class WebSocketClient : MonoBehaviour { [SerializeField] private string url = "ws://localhost:3000/"; [SerializeField] private string message = "Ya-Ha-!"; private WebSocket ws; void Start() { GetComponent<Renderer>().material.color = Color.white; ws = new WebSocket(url); ws.OnOpen += (sender, evt) => { Debug.Log("open."); }; ws.OnMessage += (sender, evt) => { Message.message = evt.Data; Debug.Log(Message.message); }; ws.OnError += (sender, evt) => { Debug.Log(evt); }; ws.OnClose += (sender, evt) => { Debug.Log("close."); }; ws.Connect(); } void OnDestroy() { ws.Close(); ws = null; } public void OnClick() { ws.Send(message); } }
スクリプトを作成し、CubeのPointer Clickに「WebSocketClient.OnClick」を設定します。
サーバの作成
package.json
{ "name": "unity-network", "version": "1.0.0", "main": "app.mjs", "scripts": { "start": "node app.mjs" }, "dependencies": { "express": "^4.19.2", "ws": "^8.18.0" } }
app.mjs
import express from 'express'; import { createServer } from 'node:http'; import { WebSocketServer } from 'ws'; const __dirname = import.meta.dirname; const app = express(); const http = createServer(app); const wss = new WebSocketServer({ port: 3000 }); const wsList = []; app.use(express.json()); app.use('/', express.static(`${ __dirname }/public`)); wss.on('connection', (ws) => { wsList.push(ws); ws.on('message', (message) => { for (const websocket of wsList) { if (ws !== websocket) { websocket.send(String(message)); } } }); }); http.listen(8000);
public/index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>WebSocket</title> </head> <body> <button>click</button> <script> const socket = new WebSocket("ws://localhost:3000"); socket.addEventListener('open', () => { console.log('open.'); }); socket.addEventListener('message', (evt) => { console.log(evt); }); document.querySelector('button').addEventListener('click', () => { socket.send('click!'); }); </script> </body> </html>
- Expressでサーバを立てる
- WebSocketでメッセージを受信した際に送信元以外にそのメッセージを送る
- Webページをホスティングする(WebSocketでメッセージ受信時にログを表示する)
を実装しました。
npm start
で起動し、ブラウザで、localhost:8000にアクセスします。
これで準備OKです。
挙動確認
Unity側でCubeをクリックすると、ブラウザにログが表示されます。
逆にブラウザのボタンをクリックすると、Unity側に「click!」と表示されます。
これが、WebSocketの力です。
今回は簡易的に、「自分が発信したメッセージ以外を他の相手に送る」という実装になっているため、ブラウザでlocalhost:8000をたくさん開くと、ボタンをクリックした際に他のWindowには「click!」が送信されます。本当はUnityから送信されたメッセージか、ブラウザから送信されたメッセージかを判別するための工夫を実装した方が便利なのですが、今回は簡易版ということで、そこには触れません。
せっかく、メッセージのやり取りができるようになったので、ブラウザからCubeの色を変更できるようにしてみます。
Unityの修正
Assets/Scripts/WebSocketClient.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using WebSocketSharp; public class WebSocketClient : MonoBehaviour { [SerializeField] private string url = "ws://localhost:3000/"; [SerializeField] private string message = "Ya-Ha-!"; private WebSocket ws; void Start() { GetComponent<Renderer>().material.color = Color.white; ws = new WebSocket(url); ws.OnOpen += (sender, evt) => { Debug.Log("open."); }; ws.OnMessage += (sender, evt) => { Message.message = evt.Data; Debug.Log(Message.message); }; ws.OnError += (sender, evt) => { Debug.Log(evt); }; ws.OnClose += (sender, evt) => { Debug.Log("close."); }; ws.Connect(); } void Update() { switch (Message.message) { case "red": GetComponent<Renderer>().material.color = Color.red; break; case "blue": GetComponent<Renderer>().material.color = Color.blue; break; case "green": GetComponent<Renderer>().material.color = Color.green; break; default: GetComponent<Renderer>().material.color = Color.white; break; } } void OnDestroy() { ws.Close(); ws = null; } public void OnClick() { ws.Send(message); } } public class Message : MonoBehaviour { public static string message = ""; }
HTMLの修正
public/index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>WebSocket</title> </head> <body> <button id="click">click</button> <button id="red">red</button> <button id="green">green</button> <button id="blue">blue</button> <script> const socket = new WebSocket("ws://localhost:3000"); socket.addEventListener('open', () => { console.log('open.'); }); socket.addEventListener('message', (evt) => { console.log(evt); }); document.getElementById('click').addEventListener('click', () => { socket.send('click!'); }); document.getElementById('red').addEventListener('click', () => { socket.send('red'); }); document.getElementById('green').addEventListener('click', () => { socket.send('green'); }); document.getElementById('blue').addEventListener('click', () => { socket.send('blue'); }); </script> </body> </html>
挙動確認
ブラウザ上のボタンを押すと、Cubeの色が変わるようになりました。
今回は以上です。