PDCAを回す

#はじめに
この記事は、[VCI Advent Calendar 2019](https://qiita.com/advent-calendar/2019/vci)の1日目の記事です。

#回る
![PDCA_RotateA.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/ed88a20a-181c-6446-0744-1953099b219e.gif)
#投げる
![PDCA_RotateB.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/3889e9b4-c518-e285-df9d-a132f8a4fdd8.gif)
~~PDCAは投げ捨てるもの~~
#サンプル
[PDCA - アイテム情報確認 - THE SEED ONLINE(α)](https://seed.online/user/items/f4a91e8dd762451442640a79d7374cad84f85de5b87a8329bfcb820b2a4bbf0c)
#作り方
作成に必要な各アプリ(特にUnity)の導入についてはこちらを確認してください。
[Virtual Cast Wiki : 初めてVCIを作成する](https://virtualcast.jp/wiki/doku.php?id=vci:beginner)

ざっくりいくよー。
##1.VCIObjectの作成
Hierarchyを右クリックして、
VCI ＞ PlainVCI

を選択して作成します。
そして下記画像のように入力していきます。
![PDCA 0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/771dbb71-002a-0a6f-5d02-09eb1a6c52ba.png)

##2.VCI SubItemの作成
上記で作成したHierarchyのVCIObjectを右クリックして、
Create EmptyでGameObjectを作成します。
####VCI SubItemの追加・設定
作成したGameObjectを選択して、名前を変更し、Inspector画面からAddComponentをクリックして
検索から
「VCI」
を入力します。
すると、「VCI SubItem」が表示されるのでそれをクリックしてアタッチしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/dc6b9bb3-11d5-3b6d-ea36-4b4e6e07702b.png)
今回は、

 - 回っているPDCAを掴みたい
 - 回っているPDCAを投げ捨てたい
 - 回っているPDCAを大きくしたり小さくしたい

という考えなので、

 - Grabbable
 - Scalable
    - Uniform Scaling

の3つにチェックを入れてください。
意味としては

 - Grabbable　掴めるか
 - Scalable　両手で掴んで大きさの変更が可能か
    - Uniform Scalable X,Y,Zの比率を維持した拡縮に制限するか

になります。
VCI SubItemについての詳細はこちら
[VCI SubItem Component](https://virtualcast.jp/wiki/doku.php?id=vci:sdk:subitem:introduction&s[]=uniformscaling)

####Rigidbodyの設定
VCI SubItemが追加される際に、Rigidbodyコンポーネントが自動で追加されます。
[Unity Documentation:Rigidbody](https://docs.unity3d.com/ja/2017.4/Manual/class-Rigidbody.html)
重要な箇所のみざっくり説明します。
> Mass 単位はKg
> Drag 抵抗。値が低いと、オブジェクトが重く見えるようになります。この値が高いと、軽く見えます。 Drag の通常の値は、0.001 (金属の塊) と 10 (羽) の間です。
> Angular Drag　回転の抵抗
> Use Gravity　重力の影響を受けるか
> Is Kinematic  物理エンジンの影響を無効にするか
> Freeze Position XYZ軸の移動を制限するか
> Freeze Rotation XYZ軸の回転を制限するか

例えば猫耳を体に付けるためのVCIを作成したい場合は

- [ ] Use Gravity
- [x] Is Kinematic

にすると良いです。

####Box Colliderの追加
VCIの時と同様にBoxを入力するとBox Colliderが出てくるのでそれを選択します。
Box Collider 2Dを選択しないように注意して下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/e089ac16-956a-b3e5-9d39-4883c223adad.png)

大きさは下記を参考にしてください。
![PDCA 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/ee3dba2a-75e8-80bb-7dd6-d58d451c12fd.png)

Box Colliderの範囲がそのSubItemを掴める範囲になります。
また、Is Triggerについてですが、

- [ ] Is Trigger：物理的な当たり判定がある
- [x] Is Trigger：物理的な当たり判定がない

ぐらいに思っていれば最初はOKです。装着VCIの場合は基本的にチェックが付いていることをお勧めします。

##3.回転するGameObjectの作成
前回同様に、空のGameObjectを作成して、名前を変更します。
このGameObjectの下に回転させるGameObjectを設置していきます。
![PDCA 18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/ae901b90-a101-ad88-0654-06caffc9aca2.png)

##4.描画用GameObjectの追加
####テキスト裏の白背景の追加
文字の後ろに白背景を用意したいので、HierarchyのRotatePDCAを右クリックして
3D GameObject > Plane
を選択してPlaneを作成します。初期値がすごく大きいのでScaleを小さくしましょう。
![PDCA 26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/a51423af-5457-7411-4dff-47bc3143290f.png)

####テキストの追加その１
HierarchyのRotatePDCAを右クリックして
VCI > Text
を追加します。
うまく動作しない場合は下記URLを参照してください。
[VCI Text (TextMeshPro)](https://virtualcast.jp/wiki/doku.php?id=vci:sdk:text:introduction)
![PDCA 34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/0be08747-9b02-a9a3-4827-d40ecbe9aa9b.png)
作成したら、上記画像のように値を入力します。

####テキストの追加その２
Hierarchyから、上記で作成したTextをコピーして同じところに貼り付けます。
Rotationを180度回転させます。
![PDCA_00 40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/4199ac2a-2697-4677-22eb-e7ffec367791.png)

##5.スクリプトの追加
今回は回転させるためのスクリプトの作成が必要になります。
コピペでOK。ということでもいいと思いますが少し解説します。
全文はこちら

```lua:main.lua
---@type ExportTransform @回転させるGameObjectをGetSubItemしたもの
local PDCARotate = vci.assets.GetSubItem("RotatePDCA")
---@type number @Y軸の回転角度
local RotateY_Axis = 0

---全ユーザーで毎フレーム呼ばれる
function updateAll()
    RotateY_Axis = RotateY_Axis + 2
    PDCARotate.SetLocalRotation(Quaternion.Euler(0,RotateY_Axis ,0))
    if RotateY_Axis == 360 then 
        RotateY_Axis = 0
    end
end
```

####GetSubItem()
まずは始めの1文です

```lua
---@type ExportTransform @回転させるGameObjectをGetSubItemしたもの
local PDCARotate = vci.assets.GetSubItem("RotatePDCA")
```

GetSubItemの解説はこちらとこちらに任せるとして、
[バーチャルキャストのVCIスクリプトの例](https://qiita.com/sakano/items/adc88174a7dfd32ae248)
[ExportTransform](https://virtualcast.jp/wiki/doku.php?id=vci:script:reference:exporttransform&s[]=getsubitem)
今回は「subItem VCI」の付いたGameObject名ではなく、「subItem VCI」の付いたGameObjectの子供のGameObject名を記載しています。
そう、**関数名はGetSubItemなのですが、別にSubItemじゃないGameObjectもGetSubItemできます。**
ちなみにSubItemじゃないGameObjectの位置は同期されません（初期位置固定）
今回はPDCAが回っていることが重要で皆が同じPDCAの位置を共有している必要はないため、回転位置を同期しない実装にしています。
~~リアルでも共有って難しいよね~~

####updateAll()
updateAll関数についての注意点を少し。

```lua
---全ユーザーで毎フレーム呼ばれる
function updateAll()
    RotateY_Axis = RotateY_Axis + 2
    PDCARotate.SetLocalRotation(Quaternion.Euler(0,RotateY_Axis ,0))
    if RotateY_Axis == 360 then 
        RotateY_Axis = 0
    end
end
```

全ユーザーで毎フレーム呼ばれますが、全ユーザーの秒間のフレーム数・開始タイミングはそれぞれ異なります。

これはお互いがPDCAの**C**を指している様子
![PDCA_Rotate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/cc1f1024-2022-b19e-0a81-41fc4ed84e38.gif)
このような実装をする場合には、お互いが秒間フレームが異なる状態でも問題のないVCIである必要があります。

#最後に
Export VCIボタンを押して.vciファイルを作成します。
あとはTHE SEED ONLINEにアップすればバーチャルキャスト上で利用することができるようになります。