#はじめに
これは「toio™(ロボットトイ | toio(トイオ)) Advent Calendar 2019」の1日目の記事になります。
この記事ではUnityとtoioの連携方法を記します。
以下の記事・サイトを参考にしました。
#toio.js とは
toio.js は Node.js を用いたtoio公式のライブラリです。
パソコン側からcoreCubeを動かしたり、マット上の位置を取得したり出来ます。
今回はこれを使ってマット上のcoreCubeにUnity上のCubeを連動させたいと思います。
#環境
OS : MacOS High Sierra 10.13.6
#下準備
##Unity
###Unity Hub のインストール
Unity Hub を入れます。
こちらのUnityHubをダウンロードからインストーラをダウンロードできます。
unity hubを起動してインストールで最新バージョンのUnityを入れます。
このとき、Visual Studioも一緒にインストールします。
###UniRx
Unity Hub で新規プロジェクトを作成します。
プロジェクトが開いたらAssetストアで UniRx をダウンロード、インポートします。
すると、Assetsフォルダ下にPluginsフォルダができ、その中にUniRxが入ります。
###C# websocketライブラリ
こちらからライブラリをダウンロードして解凍します。
中にある websocket-sharp.csproj をVisualStudioで開きビルドすると bin/Debug 下に websocket-sharp.dll が出来ます。
この websocket-sharp.dll を先ほど作成したプロジェクトの Assets/Plugins に入れます。
これでUnity側の下準備は完了です。
##toio.js
###brew install yarn
yarn に関しては公式では npm で入れていますが、
npm install -g yarn
私は以下のように brew を使いました。
brew install yarn
権限が必要だったり入れ難かった覚えがありましたが、なんかと入れたようです。
良くないことをしたかも知れません。
###toio.js
次に toio の github から toio.js を clone します。
公式曰く、以下のコマンドでパッケージのbuildまで済みます。
yarn example:hogehoge でサンプルプログラムが動きます。
git clone https://github.com/toio/toio.js.git
cd toio.js
yarn install
yarn build
yarn example:keyboard-control
coreCubeの電源を入れて接続され方向キーで動いたらオッケーです。
僕は接続されなかったのでパソコンを再起動したら動きました。
#実装
##Unity側
SceneにCreateから3D Object/Cubeを置きます。
またCreateからUI/Buttonを置いておきます。
Cube に Add Component/NewScript でPositionSyncというスクリプトをつけます。
以下、@nmxi さんの記事*から拝借したコードを改変して書いた中身です。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using WebSocketSharp;
using UniRx;
public class PositionSync : MonoBehaviour
{
[SerializeField] private string _serverAddress;
[SerializeField] private int _port;
[SerializeField] private SyncPhase _nowPhase;
private GameObject tA;
private WebSocket ws;
string message = "";
string messageA = "";
public float span = 0.5f;
public enum SyncPhase
{
Idling,
Syncing
}
private void Awake()
{
tA = GameObject.Find("Cube");
_nowPhase = SyncPhase.Idling;
}
void Update()
{
string[] m = message.Split(',');
switch (m[0])
{
case "A":
if (message != messageA)
{
////サイズの変更
//マット
//559mm 410points
//toioコアキューブ
//31.8mm about 23.3point
tA.transform.position = new Vector3(-(float.Parse(m[2]) - 250.0f) / 10.0f, tA.transform.position.y, -(float.Parse(m[1]) - 250.0f) / 10.0f);
tA.transform.rotation = Quaternion.Euler(0, float.Parse(m[3]), 0);
}
messageA = message;
//Debug.Log(m);
break;
}
}
/// <summary>
/// Get Down Start Sync Button
/// </summary>
public void OnSyncStartButtonDown()
{
var ca = "ws://" + _serverAddress + ":" + _port.ToString();
Debug.Log("Connect to " + ca);
ws = new WebSocket(ca);
//Add Events
//On catch message event
ws.OnMessage += (object sender, MessageEventArgs e) => {
message = e.Data;
};
//On error event
ws.OnError += (sender, e) => {
Debug.Log("WebSocket Error Message: " + e.Message);
_nowPhase = SyncPhase.Idling;
};
//On WebSocket close event
ws.OnClose += (sender, e) => {
Debug.Log("Disconnected Server");
};
ws.Connect();
_nowPhase = SyncPhase.Syncing;
}
public void OnChangedTargetTransformValue(Vector3 pos)
{
if (_nowPhase == SyncPhase.Syncing)
{
//ws.Send(pos.ToString());
//ws.Send("1");
}
}
}
Cube にある PositionSync (Script)の欄に
Server Address には "localhost"、Port には "8080"を入れて置きます。
先ほど置いたButtonのOn Click()に Cube/PositionSync/OnSyncStartButtonDown() を追加します。
##toio.js側
toio.js/projectsフォルダを作成し、その中にスクリプトを置きます。
今回はtoio公式のサンプルと@nmxi さんの記事*から拝借したコードを悪魔合体して以下のスクリプトを生成しました。
マット上におけるcoreCubeの絶対位置をUnityに送るプログラムです。
const { NearestScanner } = require('@toio/scanner')
var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({
port: 8080
});
var cube;
async function main() {
// start a scanner to find nearest cube
cube = await new NearestScanner().start()
// connect to the cube
await cube.connect()
}
main()
wss.on('connection', function(ws) {
//position-idに変化があった時
//移動、回転
//toioPositionを更新する
cube.on('id:position-id', data => {
ws.send("A,"+data.x+","+data.y+","+data.angle)
})
//マットから離れた時
cube.on('id:position-id-missed', () => {
// ws.send('Position Miss!');
})
});
#実行
1.coreCube の電源を入れます。
2.toio_node.js を実行します。(少しして coreCube から音がします。)
cd projects
node toio_node.js
3.Unity のプロジェクトを Run します。
4.GameView 上で Button をクリックします。
この状態でマットに置いた coreCube の位置が Unity の Cube に反映されれば成功です。
こんな感じ
[qiita用] マット上でのtoioCoreCubeの移動・回転がunityのSceneに反映されている pic.twitter.com/QJloUHmCeR
— ito.ur.right (@ito_ur_right) November 28, 2019