スペースキーじゃなくてInputFieldで

Unityで入力した文字列をサーバーに送信できるようにする

 

WebSocket Unityとサーバーの双方向通信 Unity編

この記事で書いたものをレベルアップ
リンク先のものは、スペースキーの入力を通知していますが
今回はUIで入力された文字列をサーバーに送信するようにする

用語整理

Unity
統合開発環境を内蔵したゲームエンジン
2Dはもちろん、3DやVR用アプリケーションも作ることができる
Web,iOS,Androidなど様々な機器向けにデータをエクスポートできる

WebSocket
HTML5に定義されている技術規格
クライアントとサーバー間に「ソケット」と呼ばれる
持続的な接続を確立させることで
双方向からデータの送信を開始できるようになる(らしい)
基本的なHTTPだとクライアントからだけしか
データの送信を開始できない

( Unity ) websocket-sharpライブラリ
Unityで使用するC#用ライブラリ
WebSocketが簡単に作れるようになっている
ここからダウンロードできる

Visual Studio
MicrosoftのIDE
Unityをダウンロードすると一緒についてくる
Unity2018からのUnityで使うメインエディタ

InputField
Unityのオブジェクトの一つ文字列が入力できる
子要素にTextオブジェクト、Placeholderオブジェクトがある

実装

websocket-sharpライブラリインポート

websocket-sharpライブラリのビルドは
前回の記事に書いてあるので省略

テスト用Unityプロジェクトを作成( 2D )

Assetsに子ディレクトリPluginsを作成
Assets/Plugins内にビルドしたwebsocket-sharp.dllをコピー

websocket-sharpライブラリインポート終了

ここまでは前回と同じ

 

InputField配置

HierarchyにInputFieldを配置

Create > UI > InputField

追加された
Canvasが自動で生成されてその子になっている

 

スクリプト作成

新規スクリプトを作成

Assets > Create > C# Script

編集

https://docs.unity3d.com/ja/current/ScriptReference/UI.InputField.html
ここを参考にInputFieldの制御を書く

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class InputFieldController : MonoBehaviour
{
    public string inputValue;
    InputField inputField;

    void Start()
    {
        inputField = GetComponent<InputField>();
        InitInputField();
    }

    public void InputLogger()
    {
        inputValue = inputField.textComponent.text;
        Debug.Log(inputValue);
        InitInputField();
    }

    void InitInputField()
    {
        inputField.text = "";
        inputField.ActivateInputField();
    }
}

 

スクリプトとオブジェクトのリンク

ドラッグ&ドロップでInputFieldオブジェクトにスクリプトをアタッチ

InputFieldコンポーネント内、On End Editの ” + “をクリック
すぐ下にあるアタッチしたスクリプトをドラッグ&ドロップしてリンク

On End EditはInputFieldからフォーカスが外れた時実行
On Value Changedは入力値が変更されると実行

右側のプルダウンを選択

InputFieldController > InputLogger

入力テスト

これで入力できるようになった
Playボタンを押してテスト
文字列を入力して、Enterを押すとログに文字列が表示される

WebSocket通信

今入力された文字列をWebSocketでサーバーに送信できるようにする

新規スクリプトを作成

Assets > Create > C# Script

InputField.csの入力された文字列が格納される変数は
以下のようにpublicにして他のスクリプトで使用できるようになっている

public string inputValue;

作りこんでいくにつれて文字列の入力方法が
InputFieldから音声入力に変わる予定なので
WebSocketなど中心となるプログラムは別で作って
オブジェクト指向で入力方法だけ変えられるように作る

 

新規作成したmain.csを編集

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using WebSocketSharp;
using WebSocketSharp.Net;

public class main : MonoBehaviour
{
    GameObject InputField;
    InputFieldController script;

    WebSocket ws;

    string new_inputvalue;
    string old_inputvalue;

    void Start()
    {
        InputField = GameObject.Find("InputField");
        script = InputField.GetComponent<InputFieldController>();
        Debug.Log("InputField Conected");

        ws = new WebSocket("ws://27.120.98.26:9001/");
        ws.OnOpen += (sender, e) =>
        {
            Debug.Log("WebSocket Open");
        };
        ws.OnMessage += (sender, e) =>
        {
            Debug.Log("WebSocket Receive Message Data: " + e.Data);
        };
        ws.OnError += (sender, e) =>
        {
            Debug.Log("WebSocket Error Message: " + e.Message);
        };
        ws.OnClose += (sender, e) =>
        {
            Debug.Log("WebSocket Close");
        };
        ws.Connect();
    }

    void Update()
    {
        new_inputvalue = script.inputValue;

        if (new_inputvalue == old_inputvalue)
        {
        }
        else
        {
            string send_message = new_inputvalue;
            old_inputvalue = new_inputvalue;
            Debug.Log("InputField Update");
            Debug.Log("WebSocket Send Message Data: " + send_message);
            ws.Send(send_message);
        }
    }

    void OnDestroy()
    {
        ws.Close();
        ws = null;
    }
}

スクリプトをHierarchyのCanvasでへドラッグ&ドロップでアタッチ

入力テスト②

動作するかだけ確認
Playボタンを押してテスト

回線が開いてないからエラーが出ているけど
送信しようとしているのでOK
完成!

サーバー側との通信

サーバーでPythonファイルを実行する

python3 /home/ユーザー名/python3_project/mei/version_1/arp.py

こんな感じのメッセージが出たら準備OK

INFO:websocket_server.websocket_server:Listening on port 9001 for clients..

Unity側Playボタンを押してプロジェクトを実行
コンソールに接続完了メッセージが出ると同時に
サーバー側でも接続完了メッセージ

以降文字列を入力してEnterを押すと送受信される

WebSocket Unityとサーバーの双方向通信 サーバー編

WebSocketを使ったUnityとサーバーの双方向通信の実装

前回に引き続きサーバー立てた理由にもなる企画です
後々使うことになるので試します

WebSocketを使ってUnityとサーバー間で
テキストデータを送り合うことを第一目標にしています

其の壱ではサーバー側の処理を作ります

用語整理

Unity
統合開発環境を内蔵したゲームエンジン
2Dはもちろん、3DやVR用アプリケーションも作ることができる
Web,iOS,Androidなど様々な機器向けにデータをエクスポートできる

使用されているサーバー

サーバーをたてる!(契約編)

こちらの記事でたてたUbuntu Server
このブログのファイルも置かれている

HTTP ( Hypertext Transfer Protocol )
ハイパーテキスト・トランスファー・プロトコル
リクエスト-レスポンス型のプロトコルで
ハイパーテキスト、画像、音声 などを
サーバーからクライアントへ転送できる
クライアントがサーバにリクエストを送信、レスポンスを返す
基本、この時点で初期状態に戻るので
サーバはクライアントの状態を保存しない

WebSocket
HTML5に定義されている技術規格
クライアントとサーバー間に「ソケット」と呼ばれる
持続的な接続を確立させることで
双方向からデータの送信を開始できるようになる(らしい)
基本的なHTTPだとクライアントからだけしか
データの送信を開始できない

サーバー側実装

サーバー側でのWebSocket通信の準備をします
ネット上の情報ではnode.jsを使っているものが
多いようなのですが、後でAI系のものを
組み合わせるのでPythonを使って実装します

お約束

ubuntu 14.04 のアップデートを確認

root@localhost:~# sudo apt-get update

アップデートを適用

root@localhost:~# sudo apt-get upgrade

使わなくなったパッケージを削除

root@localhost:~# sudo apt-get -y dist-upgrade

autoremove

root@localhost:~# sudo apt-get -y autoremove

aptのキャッシュを削除

root@localhost:~# sudo apt-get -y autoclean

 

Python3 環境確認

python3バーション確認

~# python3 -V
Python 3.4.3

pip3のバーションを確認

~# pip3 --version
pip 1.5.4 from /usr/lib/python3/dist-packages (python 3.4)

 

ファイル作成

新規ディレクトリ作成

 ~# mkdir /home/ユーザー名/python3_project/mei/version_1/

Pythonファイル作成
arp.py ( automatic response program )

~# vim /home/ユーザー名/python3_project/mei/version_1/arp.py

Pythonファイル編集

websocket-serverのGitページに載ってるサンプル
他のPythonでWebSocketやってた人のコードを参考に

さっきのwebsocket_serverパッケージと
ログを取るlogginを入れてます

ポート番号はGitのサンプルのまんまにしてあります

import logging
from websocket_server import WebsocketServer

PORT=9001
HOST='27.120.98.26'

#logger_setup
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(' %(module)s -  %(asctime)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)
 
#callback
def new_client(client, server):
    logger.info('New client {}:{} has joined.'.format(client['address'][0], client['address'][1]))
 
def client_left(client, server):
    logger.info('Client {}:{} has left.'.format(client['address'][0], client['address'][1]))
 
def message_received(client, server, message):
    logger.info('Message "{}" has been received from {}:{}'.format(message, client['address'][0], client['address'][1]))
    reply_message = 'Re: ' + message
    server.send_message(client, reply_message)
    logger.info('Message "{}" has been sent to {}:{}'.format(reply_message, client['address'][0], client['address'][1]))
 
#main
if __name__ == "__main__":
    server = WebsocketServer(port=PORT, host=HOST, loglevel=logging.INFO)
    server.set_fn_new_client(new_client)
    server.set_fn_client_left(client_left)
    server.set_fn_message_received(message_received)
    server.run_forever()

たぶんこれで動くはず…

 

其の弐はこちら
https://www.washio.net/wacode/websocket-unity-server-com-2/