LoginSignup
13
12

More than 5 years have passed since last update.

[Unity]WebSocketでリアルタイム処理を作る為の備忘録

Last updated at Posted at 2016-03-28

Unityで画面処理やキャラクター操作ができるようになってくると、他のユーザーとリアルタイムに連携したバトルとかが作りたくなる。
これを実現するためにリアルタイム通信の入門ステップとしてWebSocketを利用してブラウザからコマンドを入力してWebSocketサーバに接続しているクライアントのゲームキャラクターを動かすだけのシステムを作成してみた。

サーバサイド
今回はMicrosoft.WebSocketを利用して、.Net MVCでサーバ側アプリケーションを組みました。

Viewはこんな感じに作って「Connect」ボタンでサーバとの接続を確立後、「Up」「Down」「Left」「Right」でキャラクターを操作できるようにする。
キャプチャ.PNG
Viewのソース

Index.cshtml

<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が提供されているのでこれを使う。

OthersInputModel.cs
[Serializable]
    public class OthersInputModel
    {
        public string direction;
    }

適当なGameObjectを追加し、GameObjectにScriptを追加。今回はCharacterManager.csとします。
WebSocketに必要なライブラリはこちらから入手し、websocket-sharpをビルドしてAssets/Pluginにインポートしました。

CharacterManager.cs
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側のキャラクターが押したボタンの方向に動きました。

感想
今回はブラウザからの操作でしたが、操作がゲームに無事反映されてくれたので、今後はルーム設定やどのキャラクターが操作されたのかをまとめることでよりゲーム性の高い処理を実装できたらいいなと思いました。

以上。

13
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12