Unityで画面処理やキャラクター操作ができるようになってくると、他のユーザーとリアルタイムに連携したバトルとかが作りたくなる。
これを実現するためにリアルタイム通信の入門ステップとしてWebSocketを利用してブラウザからコマンドを入力してWebSocketサーバに接続しているクライアントのゲームキャラクターを動かすだけのシステムを作成してみた。
サーバサイド
今回はMicrosoft.WebSocketを利用して、.Net MVCでサーバ側アプリケーションを組みました。
Viewはこんな感じに作って「Connect」ボタンでサーバとの接続を確立後、「Up」「Down」「Left」「Right」でキャラクターを操作できるようにする。
Viewのソース
<button id="connectBtn">Connect</button><br />
<button id="upBtn">Up</button><button id="downBtn">Down</button><button id="leftBtn">Left</button><button id="rightBtn">Right</button><br/>
Log: <pre id="log" style="width:100%; height:260px;"></pre>
<button id="CloseBtn">Close</button><br />
@section scripts {
<script type="text/javascript">
var socket;
$(function () {
$('#connectBtn').click(function () {
if (socket == null) {
try {
socket = new WebSocket('ws://' + location.hostname + ':' + location.port + '/wsserver');
socket.onopen = function (event) { log('接続'); };
socket.onclose = function onClose(event) { log('切断'); };
socket.onerror = function onError(event) { log('エラーです'); };
socket.onmessage = function onMessage(event) { log(event.data); };
} catch (e) { alert(e.message); }
}
});
$('#sendBtn').click(function () {
var obj = new Object();
obj.message = $('#message').val();
var jsonString = JSON.stringify(obj);
socket.send(jsonString);
log('send: ' + jsonString);
$('#message').val('');
return false;
});
$('#CloseBtn').click(function () {
socket.close();
socket.onclose();
socket = null;
});
$('#upBtn').click(function () {
var obj = new Object();
obj.direction = 'up';
var jsonString = JSON.stringify(obj);
socket.send(jsonString);
});
$('#downBtn').click(function () {
var obj = new Object();
obj.direction = 'down';
var jsonString = JSON.stringify(obj);
socket.send(jsonString);
});
$('#leftBtn').click(function () {
var obj = new Object();
obj.direction = 'left';
var jsonString = JSON.stringify(obj);
socket.send(jsonString);
});
$('#rightBtn').click(function () {
var obj = new Object();
obj.direction = 'right';
var jsonString = JSON.stringify(obj);
socket.send(jsonString);
});
});
function log(msg) {
var txt = $('#log').text();
txt = msg + '\n' + txt;
$('#log').text(txt);
}
</script>
サーバアプリケーション側のソースはWebSocketでググればでてくるので省略。
参考サイト:ASP.NET MVC で WebSocket サーバを作る
クライアントサイド
Unity5.3を利用しています。
ブラウザから入力した情報のJson受け取り用のModel。Unity5.3だと.Net3.5までしか対応していないので、Newtonsoft.Jsonとか使えない。UnityからJsonUtilityが提供されているのでこれを使う。
[Serializable]
public class OthersInputModel
{
public string direction;
}
適当なGameObjectを追加し、GameObjectにScriptを追加。今回はCharacterManager.csとします。
WebSocketに必要なライブラリはこちらから入手し、websocket-sharpをビルドしてAssets/Pluginにインポートしました。
public class CharacterManager : MonoBehaviour {
private WebSocket Socket;
private Queue<string> MessageQueue;
void Start () {
Connect();
}
void Awake()
{
MessageQueue = new Queue<string>();
Socket = new WebSocket("ws://localhost:61018/wsserver");
}
// Update is called once per frame
void Update () {
if (MessageQueue.Count > 0)
{
string direction = MessageQueue.Dequeue();
if (direction == "up")
{
Up();
}
else if (direction == "down")
{
Down();
}
else if (direction == "right")
{
Right();
}
else if(direction == "left")
{
Left();
}
}
}
public void Connect()
{
Socket.OnMessage += (s, e) =>
{
var data = JsonUtility.FromJson<OthersInputModel>(e.Data);
MessageQueue.Enqueue(data.direction);
};
Socket.Connect();
}
public void Up()
{
var pos = this.gameObject.transform.position;
pos.x = this.gameObject.transform.position.x;
pos.y = this.gameObject.transform.position.y + 0.2f;
this.gameObject.transform.position = pos;
}
public void Down()
{
var pos = this.gameObject.transform.position;
pos.x = this.gameObject.transform.position.x;
pos.y = this.gameObject.transform.position.y - 0.2f;
this.gameObject.transform.position = pos;
}
public void Left()
{
var pos = this.gameObject.transform.position;
pos.x = this.gameObject.transform.position.x - 0.2f;
pos.y = this.gameObject.transform.position.y;
this.gameObject.transform.position = pos;
}
public void Right()
{
var pos = this.gameObject.transform.position;
pos.x = this.gameObject.transform.position.x + 0.2f;
pos.y = this.gameObject.transform.position.y;
this.gameObject.transform.position = pos;
}
}
Socket.OnMessageで直接Up()とか呼びたかったのですが、OnMessageでの処理はMainスレッドでの処理ではないため、Queueに入力された情報を突っ込み、UpdateでQueueの情報を引っ張りだしてキャラクターを操作するようにしました。
結果
これらを実装した状態でブラウザから方向ボタンを押すとUnity側のキャラクターが押したボタンの方向に動きました。
感想
今回はブラウザからの操作でしたが、操作がゲームに無事反映されてくれたので、今後はルーム設定やどのキャラクターが操作されたのかをまとめることでよりゲーム性の高い処理を実装できたらいいなと思いました。
以上。