土と石と木を何回か叩くことで動かせるようにする

「VキャスのVCIで◯ine◯raftっぽいもの作る Advent Calendar 2024」6日目

Vキャス内で、穴を掘って、石を砕き、木を切って、組み合わせて武器を作って、何なら出てくる敵を倒して・・・
そんなことをやりたいなぁっていう試みを12月でできるところまで行こうというカレンダーの6日目です！

昨日は、[VCIのコードデバッグ可能な環境を整え](https://qiita.com/HAHURI/items/8f4248c759ecb7b17f9d)ました。
VCIをコードで制御することで、VCIを触ったら何故起こる、VCIをUSEしたらなにか起こるみたいな、ギミックを作成することができます。

◯ine◯raftでは、ブロックはそのまま手に持てるのではなく、手で掘ったりすることで持つことが可能になりますが、SAC-Craftでもそれに近しい挙動を考えてみます。
そこで、今日はまず取っ掛かりとして、土と石と木のブロックに何回か連続で触ると持ち運びできるという挙動ができるようにします。

# 土と石と木を何回か叩くことで動かせるようにする

具体的には、以下のような挙動を考えます。
・何もしない状態では、ブロックを持ったりできないようにする
・持ち運べる状態のブロックは、最初の状態より小さく、ちょっとその場でズレた状態になる
・土は5回連続で触れたら持ち運べる状態になる（柔らかいので5回）
・石は20回連続で触れたら持ち運べる状態になる（硬いので20回）
・木の幹は10回連続で触れたら持ち運べる状態になる（微妙に硬いので10回）
・木の葉は1回で触れたら持ち運べる状態になる（脆いので1回）
・持ち運んでいるブロックをUSEして離すと、話した場所で持ち運べないブロックに戻る

すべてやるのは大変なので、今日は「動かせない状態のブロックを全て5回叩いたら動かせるようになる」というところまでをやっていこうと思います。
「週類による回数の分類と動かせるブロックをUSEして離すとおける」の部分は明日書いていきます。

今日やることは以下の通り
① UnityからCubeの名称と設定を変更する
② VR内で確認しながら5回触る動かせるようになる挙動をコーディングする

それではやっていきます。

# 手順

## ① UnityからCubeの名称と設定を変更する
再度、UnityでVCToolKitを開きます。
VCIObjectを開き、Cubeの名前を変えていきます。

挙動が色ごとに違うはずなので、Cubeの色で違う名前をつけまます。
また、プログラムからその対象を操作するには、名前が異なる必要があるので、連番で番号もつけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/a696a69c-deda-5c84-0436-ba6dd3bc65b7.png)

そして、最初の段階で掴めないようにしたいので、Grabbableのチェックを解除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/b7961a0b-7bc8-80b1-e23d-c013a2f92878.png)

今回は、叩いたら持てるようにするために、最初に表示されているブロックと持てるブロックをシステム的に分けようと思います。
名前を変えたCudeをすべて選択してCtrl+Cして、Ctrl+Vでコピーします。
コピーすると画像のように、～～(1)が生成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/5852178f-138e-f73f-c638-4ae787074bb9.png)

「(1)」を一旦「_move」に全てさしかえました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/3154f615-1673-3158-ac3e-e06a07f9486e.png)

また_moveという名前のものは全て、大きさをXYZを0.15にして、Rotationを16度づつずらしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/c6634230-3442-0672-f93a-821047ee594f.png)

更に、掴めるオブジェクトには登れなくていいので、Grabbableにチェックを付けて、IsTriggerにもチェックを付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/abc8d45f-7ed9-7651-94d0-e7305947f51b.png)

これで設定変更は完了なので、再度VirtualCastへ投稿し直しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/024462c1-be9f-df2f-b52d-9c6346fd457c.png)


## ② VR内で確認しながら土を3回触る動かせるようになる挙動をコーディングする
VCIを更新したので、VR内で出し直しをします。
![20241206230454_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/8eb1e5ff-a48f-9f59-18a1-73c7b9da2424.jpeg)
![20241206230500_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/cf072ba3-1ff0-d8df-58ee-ef06bb2c22a9.jpeg)

Visual Studio Codeを開き、VCIのmainファイルを開きます。
まずは、ブロックを連続で5回触れたら表面にある動かないオブジェクトを見えない状態にするという処理を書きます。

コードの書き方としては、触った判定が5回連続であればその関数から対象オブジェクトを触れないほど小さくするとともに触れない場所にふっとばすということを書きます。

同じものに触れるということで判断するので、判断用の関数を作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/358fb237-c271-92eb-900b-c58951783915.png)

そして、触れたというのは、アバターが触れたなら[onCollisionEnter](https://developer.virtualcast.jp/vci-docs/api/events/onCollisionEnter.html)という関数、他のVCIアイテムで触れたならば[onTriggerEnter](https://developer.virtualcast.jp/vci-docs/api/events/onTriggerEnter.html)でそれぞれ判定できます。
そこで、連続で触れればカウントアップし、別のものを触れたら1に戻るという関数を書きます。
更に、5回になったときに、表面に出ているブロックを1/100のサイズにし、更に座標系の100,100,100の場所に移動してさわれないようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/9212a0dc-fe87-0f1e-1be6-eab586fa4408.png)
これで、掴むことのできない状態のブロックを連続で5回触ると、そのブロックが消えて、触れるブロックが露出するということができます。

コードを解説すると
まず、前触ったアイテムと同じであれば、カウントアップし、そうじゃなければ1回に戻す記述。
```Lua
if flg.item == subItemName then
    flg.count=flg.count+1
else
    flg.item = subItemName
    flg.count=1
end
```

5回以上という判定になったら、そのブロックをふっとばす処理
```Lua
if flg.count>5 then
    local item = vci.assets.GetTransform(flg.item)
    item.SetLocalScale(Vector3.__new(0.001, 0.001, 0.001))
    item.SetLocalPosition(Vector3.__new(100, 100, 100))
end
```

という意味合いになります。

# おわりに
今日は、ブロックを連続で叩いたら全て同じ回数で動かせるという状態になりました。
これは土で想定したルールなので、木と石と葉はルールに従っていません。

明日は、場合分けを実装していこうと思います。