[VR出社] VR世界内からチームと一緒に働けるのか？

# はじめに

こちらは [Unity #3 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/unity3) 1日目の記事です

![kintonehacknight.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/2c9a3dd4-cd90-8ffb-0ca3-9e5c267af2cc.jpeg)

先日[Cybozu Days 2019](https://cybozuconf.com/)の **kintone hack NIGHT** というイベントで Unity x kintone の連携デモを披露しました。

kintone hack NIGHT はkintoneをテーマとしたカスタマイズをプレゼンする大会で、私は惜しくも順位が2位でした。大会の全体的な様子は下記の記事で読むことが出来ます

- [VRや社内RPG、オタク対応まで熱いLT満載だったkintone hack NIGHT](https://ascii.jp/elem/000/001/972/1972321/)


せっかくなので、kintone hack NIGHTでお見せしたデモがどういう仕組だったのかをここで紹介したいと思います。


# デモした内容

## ストーリー
- kintoneはチーム内の情報を共有するためのプラットフォーム
- 家からでも、出張先からでも、kintoneにつなげれば一元管理された情報にアクセスができ、チームとの情報共有がスムーズになる
- 故に、kintoneは様々な働き方をサポートしてくれる
- だったら、**VR世界内からkintoneにアクセス出来れば、人ってVR世界内から働けるんじゃね？在宅勤務じゃなくてVR出社出来るんじゃね？**(強引)

っというのが超絶ざっくりとしたストーリーでした。

![どこからでも働ける.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/913e9c2c-1c70-b145-bc0a-6c90c661600d.png)


## 連携内容
Unityで開発したVR世界から、様々な情報が登録されているkintoneのアプリ(ウェブデータベース)からデータを取得し、VR世界に反映させるデモをお見せしました。内容としては4つほどデモを紹介しました：

- kintoneのお知らせ掲示板アプリの内容をVR掲示板に表示させるデモ
- kintoneの案件管理アプリの売上データをVRで表現させるデモ
- 最新の売上データをVR世界内に反映させるデモ
- 自分に回ってきたワークフローを承認するデモ

# デモの詳細
## VR世界
まず事前にUnityで自前のVR世界を作りました。今まで触ったことがなかったので初めての体験だったのですが、神にでもなったような気分で色々なオブジェクトを配置出来たのは楽しかったです。そしてUnity Asset Storeの存在が物凄くでかいことを感じました。クリエイターの皆さん、本当に感謝しかないです・・・

そして出来上がったのがこんな感じのVRワールドです：
<img width="830" alt="VR世界1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/4082ef11-49a8-e24e-4193-7f4a35fb96be.png">
<img width="828" alt="VR世界2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/d33d2450-7a95-d9a0-d3a2-c538ea3c10b2.png">

使用したAssetは下記の通りです：

- [Baker's House](https://assetstore.unity.com/packages/3d/environments/fantasy/baker-s-house-26443)
- [Billboard](https://assetstore.unity.com/packages/3d/environments/urban/billboard-9700)
- [Low Poly Mini Village Free](https://assetstore.unity.com/packages/3d/environments/low-poly-mini-village-free-131677)
- [Lowpoly Simple House](https://assetstore.unity.com/packages/3d/characters/lowpoly-simple-house-117348)
- [Medieval Gold](https://assetstore.unity.com/packages/3d/props/medieval-gold-14162)
- [Menu Chalk Board](https://assetstore.unity.com/packages/3d/characters/menu-chalk-board-101989)
- [5 animated Voxel animals](https://assetstore.unity.com/packages/3d/characters/animals/5-animated-voxel-animals-145754)

使用したプレイヤーアバターは[5 animated Voxel animals](https://assetstore.unity.com/packages/3d/characters/animals/5-animated-voxel-animals-145754)のペンギンです：
<img width="298" alt="player.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/5529bb19-8acd-cc50-2ea2-216aea8d27cd.png">


## スクリプト
Unity内のオブジェクトに追加したC#のスクリプトを通してkintoneのREST APIを叩き、レスポンス内容をVR世界に反映させました。基本的な前準備やREST APIの叩き方についてはこちらの記事で確認が出来ます：

- [UnityからkintoneのREST APIを叩く方法](https://qiita.com/will-yama/items/19078a905ef4207977e4)

では、実際に一つ一つのデモに内容を解説していきます。

### kintoneのお知らせ掲示板アプリの内容をVR掲示板に表示させるデモ
総務部や情シスが社員に共有したい情報を記録する『お知らせ掲示板』というアプリを事前に作りました。
<img width="796" alt="スクリプト_お知らせ掲示板アプリ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/3f76558f-52d1-1344-a0b8-77bd6a3767bd.png">

kintoneのポータルに表示させることに寄って、社員がkintoneにログインする際に重要な情報をすぐに確認することができます。

重要な情報なので、VR世界内から業務する場合もお知らせ掲示板の内容を確認する必要がありますね。

VR世界内には、[Menu Chalk Board](https://assetstore.unity.com/packages/3d/characters/menu-chalk-board-101989)アセットをシーンに配置後、お知らせ掲示板アプリの最新のレコード情報をkintone REST APIで取得するスクリプトを付け足しました。kintoneの[レコードの一括取得API](https://developer.cybozu.io/hc/ja/articles/202331474#step2)はクエリを指定することで取得するレコードを細かく絞るが出来るので、下記のクエリで最新のレコード情報1件を取得しました：

```cs
string query = System.Uri.EscapeDataString("order by recordid desc limit 1");
```

そして取得した情報の中の《お知らせ日》、《お知らせ時間》、《お知らせ内容》を先程のアセットのTextコンポーネントのプロパティを更新して表示させました。
<img width="818" alt="スクリプト_お知らせ掲示板反映.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/dcd7ccd7-58f1-e791-c5fa-418401dd9121.png">

社員に共有したい大事な情報がVR世界に届きました！
これでVR世界内から働ける環境に一歩近づけましたね。

参考にした情報はこちらです：

- [レコードの一括取得API](https://developer.cybozu.io/hc/ja/articles/202331474#step2)
- [kintoneアプリに溜めたゲームスコア情報をUnity内に表示させる](https://qiita.com/will-yama/items/489b1f411e59bc95af26)

### kintoneの案件管理アプリの売上データをVRで表現させるデモ
次は、営業部が案件情報を溜める案件管理アプリのデータをVRで可視化することに挑戦しました。アプリの中身はこのような内容です：
![案件管理のスクショ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/23b68c92-8514-affb-90b7-5f97ed55a155.png)

kintoneのグラフ機能を使うと集計された売上情報が見えます:
<img width="1020" alt="案件管理グラフのスクショ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/24c2adea-fc7e-b4b2-36d5-cd74187664fd.png">

VR世界内から働くのであれば、会社の売上も常に意識したいところ・・・！ということで、VR世界内に3つの透明な筒を創りました。
<img width="823" alt="スクリプト_案件管理グラフ筒.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/5ceb54f1-da3d-743f-b4f5-1976fda55a15.png">

8月、9月、10月と記載された筒・・・そう、もう察しの良い読者はこれが何かもう気付きましたでしょうか。

筒の前にキノコを配置し、プレイヤーがキノコに接触するとkintoneのREST APIが叩かれるスクリプトを走らせるように設定をしました。[レコードの一括取得API](https://developer.cybozu.io/hc/ja/articles/202331474#step2)で8月、9月、10月に売り上がったレコードの情報を取得し、月ごとの売上分のコインを点から降らせました。

![スクリプト_案件管理グラフコイン雨.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/731e41e0-a112-b22e-3aa2-2653698213af.gif)


コインを降らせる処理は各筒で並列で行いたかったため、REST APIは3つ別々に叩きました。各REST APIに使用したクエリはこちらです：

```cs
string query1 = System.Uri.EscapeDataString("sales_status in (\"受注済\") and closed_date >= \"2019-08-01\" and closed_date <= \"2019-08-31\" order by recordid desc limit 100");
string query2 = System.Uri.EscapeDataString("sales_status in (\"受注済\") and closed_date >= \"2019-09-01\" and closed_date <= \"2019-09-30\" order by recordid desc limit 100");
string query3 = System.Uri.EscapeDataString("sales_status in (\"受注済\") and closed_date >= \"2019-10-01\" and closed_date <= \"2019-10-31\" order by recordid desc limit 100");
```

20秒くらいしてから、筒の中に多くのコインが溜まりました。
どうでしょう、先程お見せしたkintoneのグラフにそっくりですよね。

<img width="557" alt="スクリプト_案件管理グラフコイン雨結果.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/e1cc1848-e392-39ca-cdc7-fa1232e954c9.png">

10月、とても売り上がっていますね！

このように、VR世界内にkintoneアプリの集計データを可視化することが出来ました。情報共有がうまく出来そうで、VR世界内から働ける環境にまた一歩近づけた気がします。

### 最新の売上データをVR世界内に反映させるデモ

kintoneのグラフは一度ブラウザに表示したら、たとえ新しいデータがアプリに入ってきても表示内容はブラウザを更新するまで変わりません。

ですがこのVR世界内のグラフでしたら最新のデータも反映されますよ！ということを見せたかったので、定期的に案件管理アプリに対してREST APIを叩いて、新しいデータが入っているかどうかを確認しました。これを実現させるために、レコードに「Unity Deploy Status」というチェックボックスフィールドを設け、すでにグラフに反映済のレコードはここにチェックが入るようにしていました。
<img width="493" alt="案件管理チェックボックス.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/c0bd6300-caf4-a48b-e1cc-07edb426d918.png">

つまり、まだグラフに反映されていない新規レコードは『受注済でかつUnity Deploy Statusにチェックが入っていない』状態のレコードなので下記のクエリで絞り込めます：

```cs
string query = System.Uri.EscapeDataString("deploy_status not in (\"Deployed\") and sales_status in (\"受注済\") order by recordid desc limit 1");
```

新規レコードを探すための定期的なREST APIコールはInvokeRepeatingメソッドで実装しました：

```cs
// Start is called before the first frame update
void Start()
{
    InvokeRepeating("SeekAndDeployNewCoin", 4.0f, 4.0f);
}
```

見栄えが良いデモのために4秒に一回という短い間隔で新規レコードを探すようにはしていましたが、実際にの運用としてはもっと長い間隔で良いと思います。

新しいデータを発見した際には、VR環境内では新しいコインをinstantiateし、関連するレコードの「Unity Deploy Status」にチェックが入るように[レコードの更新API](https://developer.cybozu.io/hc/ja/articles/201941784)を叩きました。
![スクリプト_案件管理グラフコイン雨追加.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/07557544-759d-e42b-ef9a-a9d9c464f914.gif)


チャリチャリチャリーン♪

あれ？VR出社した方が最新の情報に気付きやすいのでは？

### 自分に回ってきたワークフローを承認するデモ
最後のデモではワークフローをVR環境内で処理するデモをお見せしました。

kintone内で自分が承認する必要があるアプリのレコードは自動的にポータル画面に表示されるようになっています。下記のスクリーンショットを見ると、kintoneにログインしてるユーザに対して《契約書管理アプリ》から4件、《休暇申請アプリ》から3件、《議事録管理アプリ》から2件ワークフローが回ってきてるのがわかります。
<img width="332" alt="Screen Shot 2019-11-30 at 9.30.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/9063cab3-7b7a-3614-ea9d-145dd7b2fbfc.png">

つまり、承認するレコードがいっぱいあるっということですね。

VR世界内でこれを表現するために、まずゲーム起動時にこの3つのアプリに対して下記のクエリを含む[レコードの一括取得API](https://developer.cybozu.io/hc/ja/articles/202331474#step2)を叩きました：

```cs
string query = System.Uri.EscapeDataString("Assignee in (\"{ログイン名}\")");
```

上記の**{ログイン名}**には、APIを叩いてるユーザのログイン名を入れています。こうすることにより、アプリの中の『作業者が{ログイン名}になっているレコード』だけが抽出することができます。

そして各アプリからのレスポンスに入っていたレコードの分だけ、動物のprefabをinstantiateしました。わかりやすく、使用してたアプリのアイコンに合わせたprefabを使いました。
<img width="765" alt="スクリプト_ワークフロー表現.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/0bffeb47-49aa-b1c4-922d-f0a154208c09.png">

各動物には当たり判定とスクリプトが付与し、プレイヤーがぶつかった際にはいきよいよく動物がぶっ飛ぶようにしました。

![スクリプト_ワークフローぶつかり.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/c06699dd-18be-afa8-1349-c9c530551108.gif)

そしてぶっとんだ動物はそのまま[レコードのステータスの更新API](https://developer.cybozu.io/hc/ja/articles/204791550)を叩くようにしました。このREST APIは**アプリID**、**レコードID**と**ワークフローのアクション名**を指定すると、ワークフローのステータスを一つ進めることが出来ます。つまり、API経由で承認が出来ます。
<img width="650" alt="Screen Shot 2019-11-30 at 16.14.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/72c45e30-9b42-dfed-38c8-c51151207019.png">


実は動物をinstantiateした際には、どの**アプリID**と**レコードID**と関連しているかの情報をオブジェクト名に含めていました。例えば犬のアイコンの休暇申請アプリのレコード2番に関する動物に関しては、DOG-2という名前を設定しており、これでリクエストに含める**アプリID**と**レコードID**を判断することが出来ました。アクション名に関してですが、今回はデモ用だったので『承認』というアクションを決め打ちにしていました。
<img width="499" alt="Screen Shot 2019-11-30 at 15.58.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/1b961b2f-6474-1143-ba0c-9bf9d84b0274.png">

[レコードのステータスの更新API](https://developer.cybozu.io/hc/ja/articles/204791550)の叩き方については、別記事にまとめました。

- [Unityからkintoneアプリのレコードを承認する方法](https://qiita.com/will-yama/items/f76ad908df36e9d4626f)

各動物にこのAPIを叩くスクリプトが入っているため、そのまま複数の動物にぶつかれば、kintoneには実装されていない**一括承認**もUnity内で軽々と実行することが出来ました。
![ワークフロー一括承認.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/6a454f35-9657-bdbe-f7b8-fd545027947a.gif)


## Oculus Goでのデモ
最初の3つのデモはMacの実行ファイルで行い、最後のデモだけOculus Goで行いました。全部Oculus Goでデモしても良かったのですが、kintone Hack Night では見栄えが結構重要視されていたので、世界観が伝わりやすい三人称視点のデモを多めに入れ、最後のシメはOculus Goで行いました。

と い う の は 建 前 で し て

これ、デモの練習中に気づいたことなのですが、このkintone連携のデモ、視聴者に結構な頻度でブラウザのkintone画面を見せる必要があったんです。『kintoneだとこうブラウザで表示されていますが、VR世界だとこう表現出来るんです！』みたいな解説が多くて。Oculus Go被り始めると、PCに表示されているブラウザが見れなくなるので、しょっちゅうつけたり外さなくちゃいけなくて、デモ栄えが悪くなります。

という裏話があり、Oculus Goのデモは最後に持ってきました。

Oculus Goでもkintone連携のデモはほぼ問題無く動かせました。ただ、コインを大量に降らせるシーンではOculus Go自体のスペックでは処理落ちが発生したので、調整が必要でした。他のオブジェクトの影をBaked Lightingで実装して実機への負荷を減らしたり、コインのprefabのCollision detectionをContinuous dynamicに変更してから、実感的に処理速度が改善されました。

![hmd.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/687b9f6e-aaee-4c48-3cfe-6b7c39257368.jpeg)

# VR世界内から我々はチームと一緒に働けるのか？

## 個人的な意見
技術的な面から見れば、たとえ他のチームメンバーがVR世界にいなくても、全然一緒に働けると思います。

kintoneで情報共有がされていれば、アプリの中の情報はREST APIで取得が可能ですし、REST APIで情報の更新やワークフローの承認も可能です。他にレコード内の[コメントの取得](https://developer.cybozu.io/hc/ja/articles/208242326)や[コメントの投稿](https://developer.cybozu.io/hc/ja/articles/209758903)なども可能です。アプリやレコードに権限の設定がされたとしても、パスワード認証(またはOAuth認証)でREST APIを叩けば権限が認証ユーザに正しく適用されて、レコードの閲覧/追加/更新/削除は制御されます。

ただ実際に働いている会社で実装するとしたら、ハードルとしては：
1. 会社が基本的な情報共有プラットフォームとしてkintoneを活用していること
2. VR出社という働き方を会社が受け入れてくれること

の2点が挙げられます。

1点目については、まぁ、情報共有プラットフォームとして非常に効率に良いkintoneを是非全社で導入してくださいとしか言えません＼(^o^)／

2点目については、他のチームメンバーに『見えないところで本当に働いてるのか？』と思われちゃいそうですかね。在宅勤務であれ、VR出社であれ、仕事の結果がきちんとkintoneのような情報共有プラットフォームに反映されていれば、個人的には問題は無いと思っています。

kintoneに寄るVR出社、現実味が出ましたでしょうか。

## これから期待すること

kintoneのREST APIの拡充です！！

アプリのレコードに対してのREST APIはたっぷりとあるので満足しているのですが、kintoneでの情報共有って[スペース](https://jp.cybozu.help/k/ja/user/basic/space_summary.html)(掲示板のような機能)の活用も大事なんですよね。そしてREST APIで取得出来るスペース情報が限られているというのが現状です(2019/11/30現在)。

- スペース一覧の取得API
- スペースのスレッドコメント情報の取得API
- スペースのスレッドコメントへの返信API

この3つのようなAPIがあればVR世界内でも情報共有が一段とレベルがあがり、だいぶVR出社の実現が増します。

そして欲を言うならば、

- kintoneの通知取得API

も充実して欲しいです。会社規模でkintoneを使っていると、膨大なkintone通知の処理を行う必要があります。2次元(ブラウザ)ではなく、3次元(VR世界)で通知の内容を表現することにより、より効率よく通知内容の対応ができ、kintoneでの情報共有がスムーズになると信じています。

# 終わりに
長い記事に付き合ってくださってありがとうございます。

VR出社する方法は色々とあると思うので、これからも探っていきたいと思います。

まだkintoneを触ったことが無い方がいれば、下記に参考になるリンクをリストしますのでこれを機に開発者ライセンスなど取得してREST APIでの連携に挑戦していただけると幸いです٩( 'ω' )و

- [kintone 開発者ライセンス（開発環境）](https://developer.cybozu.io/hc/ja/articles/200720464)
- [開発プラットフォームとしてのkintone](https://developer.cybozu.io/hc/ja/articles/210064823)
- [kintone開発前によくある質問](https://developer.cybozu.io/hc/ja/articles/213504206)
- [UnityからkintoneのREST APIを叩く方法](https://qiita.com/will-yama/items/19078a905ef4207977e4)
- [kintoneアプリに溜めたゲームスコア情報をUnity内に表示させる](https://qiita.com/will-yama/items/489b1f411e59bc95af26)
- [Unityからkintoneアプリのレコードを承認する方法](https://qiita.com/will-yama/items/f76ad908df36e9d4626f)