運動不足解消のためにclusterでラジオ体操ワールドを作った（cluster SDK トリガー使用）

##はじめに
自粛生活並びに在宅勤務による最もわかりやすい身体への影響は、ずばり「運動不足」でしょう。
弊社では以前一度、テレカンでラジオ体操の会が開催されましたが、
これをもっと面白くできないかということで、流行りのclusterを使って下記のような空間を作成しました。
![qiita_radio_illust.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/29d33b91-d477-353a-6a78-58758931ce22.png)

参加者が全員揃うと、壇上にいる見本キャラクターが音楽に合わせて体操をし始めるので、
各々が遠方に居ながらも同一の空間を共有しつつ楽しく汗を流すことが可能、という按配です。

clusterでワールド空間を作成すること自体については、 何という事はないのですが、
今回、
>参加者が全員揃うと、壇上にいる見本キャラクターが音楽に合わせて体操をし始める

を実現するために、現行のCluster Creator Kitには未実装の「トリガー/ギミックシステム」を利用してみたので、記録として簡単な手順を記しておきます。

##（前準備）ラジオ体操モーションを用意

お手本キャラにラジオ体操をしてもらうにあたって、meizuさんが配布している「[真面目なラジオ体操モーション](https://www.nicovideo.jp/watch/sm28716010)」をお借りしました。
こちらはMMD用のvmdファイルなので、Unityで扱えるanimファイルへ変換する必要があります。

**【vmdファイル→animファイルへの変換手順】**
（作業環境…Unity 2017.4.26f1）

[MMD4Mecanim (Beta)](http://stereoarts.jp/)をインストールし、プロジェクトへインポートします。
vmdファイル単独では変換作業ができないため、変換したいvmdファイルの他に、適当なMMDモデルのデータをプロジェクト内へ持ってきます。
MMDモデルを選択し、インスペクタ上の設定項目欄の「VMD」に今回変換したい「真面目なラジオ体操」を紐付けます。
![henkan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/83a8b049-e921-1781-54bd-92d5f0f2bda1.png)
変換作業が完了すると、モデルデータのプレハブが作成されるので、RigをHumanoidに変更しておきます。
さらに、プレハブ内のanimファイルを複製します。
複製することで、編集可能なanimファイルとしてプレハブ外へ取り出すことができます。
![anim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/378db814-44df-2de0-5f7d-efe10bb53661.png)
外出ししたanimファイルはパッケージ化しておきます。

##ワールド空間の作成
（作業環境…Unity 2019.2.8f1）
前述の通り、現行のCluster Creator Kitには「トリガー/ギミックシステム」が未実装のため（2020年5月時点）、
今回はcluster SDKを使用してワールドを作成しました。
初期設定など、詳しい導入方法は公式ドキュメントを参照ください。
■cluster SDK ドキュメント : https://clustervr.gitbook.io/sdk/

プロジェクトにSDKをインポートし終わったら、必要最低限要素が揃っているMinimalSampleシーンにあれこれ添加していく形でワールドを作成する方法が手っ取り早いです。
Canvas系の要素は今回不要なので非表示にしておきました。

さてラジオ体操の舞台となる会場ですが、せっかくなので、フォトグラメトリで再現した弊社会議室を使用しました。
これで在宅勤務の社員も、オフィスに来たような気持ちになれますね。
<img width="903" alt="office.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/db92b77d-9046-480a-7978-fbd2988e677d.png">


「SpawnPointEntrance」の位置を適宜調整し、あとは
オフィス内の家具や壁、床にコライダーを付けていけば、舞台となる会場の完成です。

##お手本キャラの配置
こちらもせっかくなので、お手本キャラとして弊社社長の3Dスキャンモデルを使用しました。
社長には代表してラジオ体操を常時遂行していただきます！
<img width="443" alt="スクリーンショット 2020-05-13 14.49.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/9cd87c3e-fe47-89d8-58ec-5c4c4420cb98.png">


取り込んだ社長モデルのRigをHumanoidに設定し、シーン上に配置します。
貫通させないように、コライダーも付けておきました。
<img width="735" alt="スクリーンショット 2020-05-13 14.45.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/f2d09fc0-d364-559a-42de-7dcecaac7983.png">

##アニメーションの調整

パッケージ化しておいたラジオ体操のモーションをプロジェクトに取り込みます。
Animator Controllerを作成し、空のステートへ取り込んだラジオ体操モーションを紐付けます。
このAnimator Controllerを社長モデルにアタッチしておきます。

シーン上で社長モデルを選択した状態でAnimationタブを開きます。
ラジオ体操モーションは編集できるデータになっているので、アニメーション最後の立ち姿ポーズのキーのみをコピーした上で
Create New Clipからアニメーションを新規作成します。（idleモーションと名付けておく）
<img width="914" alt="スクリーンショット 2020-05-13 15.01.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/1c7c0dc0-66c1-f029-940d-7d777cfd9785.png">
コピーしておいたキーをペーストし、上書きします。
このモーションはloopのデフォルトモーションにしておきたいので、AnimatorタブからSet as Layer Default Stateを設定します。


##ギミックの作成
シーン上に空オブジェクトを作成し、PlayableSwitchTriggerをアタッチします。

- デフォルト状態 と「ラジオ体操やめる」トリガー発動時に呼ばれるTimeLine
- 「ラジオ体操時はじめる」トリガー発動時に呼ばれるTimeLine

のちほど上記2点を作成して紐付けるため、sizeは2とし、idはそれぞれ「Idle」、「Radio」とします。
Default Indexは0（Idle）に設定します。
この時点ではDirectorはまだ紐付けされていない状態で大丈夫です。
<img width="420" alt="スクリーンショット 2020-05-13 15.21.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/5eb3652e-8271-4810-771a-5ac580a25180.png">


##TimeLineの作成
TimeLineを2つ新規作成します。
> デフォルト状態 と「ラジオ体操やめる」トリガー発動時に呼ばれるTimeLine

こちらの名前を「Idle」とし、

> 「ラジオ体操時はじめる」トリガー発動時に呼ばれるTimeLine

こちらの名前を「Radio」とします。

シーン上に空のオブジェクトを2つ作成します。
それぞれ分かりやすいようTimeLineと同一の名称にし、作成した同一名のTimeLineをアタッチします。

各TimeLineの内容は下記のような感じです。

`Idle`
![idle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/4aee40f2-b3b7-584b-d1fc-a5f64d1c2b53.png)


`Radio`
![RADIO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/5d69d3fb-6374-5b1c-6fb0-4d745a28f052.png)


「Gimmick」のPlayableSwitchTriggerに、作成したTimelineを紐付けます。
<img width="420" alt="スクリーンショット 2020-05-13 15.21.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/acb21705-a6fb-a4ff-b730-f2833341c0a7.png">


##ワールドのアップロード、イベント作成
ワールドアップロードの前に、Unityエディタ上でトリガーの動作を確認しておきます。
プレイモード中に、メニューバーのPreview -> ControlWindowからトリガーを発動させることができます。
<img width="458" alt="スクリーンショット 2020-05-13 14.56.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/70cb8f1b-cae6-e285-046f-5f3b0bc9fee1.png">

動作に問題がなければ、メニューバーのclusterSDK -> VenueUploadから、ワールドをアップロードします。
（結構時間がかかります…。）

Unityでの作業はこれで終了です。
clusterのwebサイトへログインし、イベントを作成します。
ワールドのアップロードが正しく行われていれば、会場選択画面にて作成したワールドを選ぶことができます。

##Webトリガー設定用jsonファイルの用意

[公式ドキュメント](https://clustervr.gitbook.io/sdk/guide/venue_customization/trigger_and_gimmick#triggerfile)に則ってjsonファイルを用意します。
category名は同一にし、instantはtrueで設定しておきました。

```WebTrigger.json
{
  "triggers": [
    {
      "id": "Idle",
      "category": "Timeline",
      "showConfirmDialog": true,
      "instant": true,
      "displayName" : "ラジオ体操やめる",
      "color": [ 0.0, 0.0, 0.0 ]
    },
    {
      "id": "Radio",
      "category": "Timeline",
      "showConfirmDialog": true,
      "instant": true,
      "displayName" : "ラジオ体操始める",
      "color": [ 1.0, 1.0, 1.0 ]
    }
  ]
}
```
作成したイベントページの「トリガー制御」ボタンから、
上記jsonをアップロードすると、トリガーボタンが作られ、制御可能になります。

![webtrigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/26aba503-3328-600d-c5a6-b4da5d2d2148.png)

イベント開催中は、
【参加者全員が集まったタイミングで、「ラジオ体操はじめる」ボタンを押す】
という運用方法で楽しめます！
以上、「トリガー/ギミックシステム」を使用したclusterラジオ体操ワールドの作成手順でした。

##実際の様子
プレ開催した際の様子はこちらです。
![mihon2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247873/b500bab1-7a2c-9d51-417d-c09ddb92e1c4.png)



この時はVRでの参加者が居なかったため、参加者のアバターのポーズが皆直立ですが、
実際には各々がclusterを立ち上げた画面の前でしっかりとラジオ体操に勤しんでいたことでしょう！

##備考
ラジオ体操の音源について
https://www.jp-life.japanpost.jp/radio/abt_csr_rdo_cr.html