【NeosVR】LogiX＋Node.jsでWebSocketを使ってみる

この記事は[「NeosVR reso Advent Calendar 2020」](https://qiita.com/advent-calendar/2020/neosvr_reso)および[「NeosVR Advent Calendar 2020」](https://adventar.org/calendars/5277)の21日目です。

# 自己紹介と記事について
数か月前からNeosVRを始めた初心者です。テトリスばかりやっていますが、最近LogiXの勉強も始めたので、まずは簡単なWebSocketの使い方を調べてまとめてみることにしました。

# 準備（NeosVR側）
NeosVRではWebSocketClientが用意されており、VR空間からWebSocketを使ったプログラミングも可能です。

## チュートリアルワールドに行く
ワールド一覧から「チュートリアル」を選択し「Websocket Example」のセッションをスタート。
基本的な組み方は網羅されていたため、今回はこのLogiXをほぼそのまま使います。
![2020-12-20 13.06.56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/46c660d6-576f-c5cf-8def-009f2c3962fb.jpeg)

## 処理の説明
真ん中あたりのWebSocketClientを中心として、各LogiXノード群がつながっています。
1) WebSocketの接続を開始する（`Pulse`が流れると指定されたURLに接続する）
2) WebSocketの接続が成功した時の処理
3) サーバにメッセージを送信する
4) サーバから受信したメッセージをString型で書き出す

## 自分でLogiXを組む場合
任意のオブジェクトのインスペクタより[Attach Component]->[Network]->[WebsocketClient]を追加。
関連するLogiXノードはノードブラウザの[Network]->[Websocket]にあります。

# 準備（Node.js側）
WebSocket通信を行うサーバを用意します。

## 環境
Windows10

| Package | Version | Explanation |
|---|---|---|
| Node.js | 12.19.0 | JavaScriptでいろいろできるやつ |
| [ws](https://www.npmjs.com/package/ws) | 7.4.0 | WebSocketを使うやつ<br>[Socket.io](https://socket.io/docs/v3/index.html)もありますが今回はこちらでやります | 

## パッケージを追加
```shell
npm install ws
```

## WebSocketサーバを立てる
今回はメッセージを受信すると接続しているクライアント全てにメッセージをそのままブロードキャストするようにします。

```javascript:app.js
const server = require("ws").Server;
const ws = new server({ port: 443 });

ws.on("connection", socket => {
  console.log("connected!");

  socket.on("message", ms => {
    console.log(ms);
    ws.clients.forEach(client => {
      client.send(ms);
    });
  });

  socket.on("close", () => {
    console.log("good bye.");
  });
});
```

```shell
node app.js
```

## WebSocketクライアントを追加する
NeosVRの外にクライアントを用意します。今回はChromeの開発者ツールのConsoleで実行します。
`xxxxxx`の部分は同じPCで実行しているなら`localhost`となります。

```javascript
const conn = new WebSocket('ws://xxxxxx:443');
conn.onmessage = (m) => { console.log(m.data) };
```

# NeosVRの中と外でやり取りしてみる
## まずはHello World
1) のURLを`ws://echo.websocket.org`から、自分で立てたサーバに変更して`Pulse`を押します。
サーバ側のコンソールに`connected!`と表示されれば接続は成功です。

NeosVRが遊べるPCとNode.jsを入れているPCが別だったので、LAN内のIPアドレスにしています。
（アクセスできるんですね。。。）
マルチプレイの場合のスコープは未確認ですが、また調べてみようと思います。
![2020-12-20 14.44.28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/79822dc6-c1b7-7f7a-02c4-b06ae7233b4b.jpeg)

3) に何かメッセージを入れて送信してみます。
サーバ側のコンソールと、追加したWebSocketクライアントに入力したメッセージが表示されます。
![2020-12-20 14.45.11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/18dd3a7d-f39b-edc0-212b-332ce0b8f78a.jpeg)

```shell
Hello NeosVR!
```

今度はNeosVRの外のWebSocketクライアント（Chrome）からメッセージを送信してみます。

```javascript
conn.send('Hello NeosVR! (Chrome)');
```

4) に送信されたメッセージが表示されます。
![2020-12-20 15.05.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/5ef95221-ab70-c397-36a5-e502bee344ed.jpeg)
簡単なテキストメッセージですが、NeosVR内と外でWebSocket通信をすることができました。

## NeosVR内の座標を取得する／NeosVR外から座標を操作する
チュートリアルワールドの奥に行きます。

5) 近くのユーザの座標を取得してWebSocketのメッセージとして送信する
6) 受信したメッセージが座標としてParseできればオブジェクトの座標を変更する

まずは何も考えず5) の`Pulse`を押してみます。
![2020-12-20 13.08.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/4029bce8-1935-1a4b-7b72-876b1fe8580f.jpeg)

奥にあった球のオブジェクトが自分のいた場所にワープしてきました。
![2020-12-20 14.31.01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/ed740160-679e-d781-a282-8da09dce0a67.jpeg)

サーバ側のコンソールを見るとメッセージの内容がわかります。
この形式でXYZの座標を指定してやれば、NeosVRの外から球の位置を操作できそうです。

```shell
[1.409628; 1.852089; -5.665314]
```

0.0.0の位置を指定すると、

```javascript
conn.send('[0; 0; 0]');
```

ワールドの中央に飛んでいきます。
![2020-12-20 15.31.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/baaaa50f-cf6d-992a-9c6c-6f88c3cf6ec5.jpeg)
Y座標に10を指定すると、

```javascript
conn.send('[0; 10; 0]');
```

こんなに高い位置に来てしまいました。
![2020-12-20 15.50.19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452021/b118e205-4042-c5ad-cf31-851d163ac474.jpeg)

# おわり
WebSocketを使えるようになると、VR空間と現実を連携して色々おもしろいことができそうです。

今回の記事の内容はデスクトップモード（VRHMDなし）でもできますので、NeosVRが気になっている方は試してみてはいかがでしょうか。

よければアドベントカレンダーの他の記事も覗いてみてください。
[「NeosVR reso Advent Calendar 2020」](https://qiita.com/advent-calendar/2020/neosvr_reso)
[「NeosVR Advent Calendar 2020」](https://adventar.org/calendars/5277)