持ち物の概念をつくる　その3

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

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

今日はON/OFFの状態切り替えを作っていきます。

# 持ち物の概念をつくる　その3

ON/OFFの切り替えはオブジェクト自体を消さず、サイズを操作することでそう見えるようにします。
つまり、ONのときはアクセサリー部分が極めて小さくなり板は通常サイズになり、OFFのときは板が極めて小さくなりアクセサリー部分が通常サイズになるというような処理を書きます。


# 手順
## ① USEでON/OFFを切り替わるようにする。
Visual Studio Codeを開き、EmbeddeedScriptWorkspace階層を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/981f3404-e472-011c-81e4-e9b0bae00dd7.png)

情報表示板のmain.luaを開き、コードを追記していきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/2b280c4f-b9d8-9d5a-6ffa-3c6a1b348964.png)

ON状態でOFFへの切り替えの判定を行うのは、`l_v`というオブジェクトになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/eb0b43c5-88e7-3303-e498-56412a9ce264.png)

逆にOFF状態でONへの切り替え判定を行うのは、`Cylinder`というオブジェクトです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/aeaacfed-2095-d659-3141-fcb00166c353.png)

この2つのオブジェクトのUSEを押したら、状態が変化するようにします。
この記述は簡単にすみます。
```lua
function onUse(target)
    if target == "l_v" and mode==true then
        mode = false
    elseif target == "Cylinder" and mode==fales then
        mode = true
    end
end
```
USEをしたときに、その対象がON/OFFを切り替えるオブジェクトでかつ、切り替えるタイミングのmodeのときにmodeを切り替えるという処理です。

## ② ONとOFFのサイズ変更処理を書く
modeの切り替えを書いたので、modeがONのときの処理を書きます。
これは関数として書いておいた方がほかで呼びやすいので関数を書きます。
```lua
function setON()
    Cube.SetLocalScale(Vector3.__new(0.6,0.01,0.35))
    for key, value in pairs(SubItems) do
        if key == "l_v" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.1,0.02,0.085))
        elseif key == "select" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.12,0.02,0.12))
        elseif key == "Sphere" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.2,0.2,0.2))
        else
            SubItems[key].item.SetLocalScale(Vector3.__new(0.08,0.01,0.08))
        end
    end
    Cylinder.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
end
```
ONのときに、Cube（板）と、各ボタンのサイズを視覚的に見える状態（Unityでの設定サイズ）にして、Cylinder（OFFのとき出ているアクセサリー）を小さくするという処理が書かれています。

同様に反対の記述をOFFように書きます。
```lua
function setOFF()
    Cylinder.SetLocalScale(Vector3.__new(0.1,0.01,0.1))
    for key, value in pairs(SubItems) do
        if key == "l_v" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
        elseif key == "select" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
        elseif key == "Sphere" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.2,0.2,0.2))
        else
            SubItems[key].item.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
        end
    end
    Cube.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
end
```
OFFでもONでも、腕につけるオブジェクト（Sphere）はサイズが変わらないので同じことを書いています。
※サイズ変更がないので、変更させない分岐でも良い


## ③ 昨日の設定部分の間違いを治す

ON/OFFはUSEで切り替えることを考えていました。
USEが働く条件を[公式リファレンス](https://developer.virtualcast.jp/vci-docs/api/events/onUse.html)を確認すると
> UseをするにはSubItemがGrabできる設定になっている必要があります。SubItemがGrabができるためには、自身を含む子孫にColliderがアタッチされており、かつSubItemの Grabbable が true になっている必要があります。

とあり、昨日Unityで設定したGrabbableのチェック外しをしていると、USEが機能しないことがわかります。

そこでUnityからVCToolkittを再度開き修正します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/0868e60d-55c5-84fb-07bf-18d57b479962.png)

Grabbableのチェックを付け、しかし移動できないように、RigiodbodyのConstrainsにチェックを入れて動かないようにしました。

修正したら、再度VirtualCastへ投稿（更新）します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/23624f17-2d18-de7d-dc1b-f9baf6128c0f.png)

この状態で、再度VirtualCastを起動し、VCIを更新して②で定義した関数を、USE時に実行するように記述して試してみます。
```lua
function onUnuse(subItemName)
    if subItemName == "l_v" and mode==true then
        mode = false
        setOFF()
    elseif subItemName == "Cylinder" and mode==false then
        mode = true
        setON()
    end
end
```
OFFに（`l_v`オブジェクトをUSE）したら、OFFにする関数を実行し、ONに（`Cylinder`オブジェクトをUSE）したら、ONにする関数を実行。
という記述です。

VR上で試してみます。
板のON/OFFボタンをUSEして、消える。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/5f208702-0a0c-ad55-9442-8efd4fec24d6.jpeg" width="50%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/8cf22d9c-3974-eac2-8c79-100dc5163c80.jpeg" width="50%">

そして、円柱をUSEすると、板が復帰する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/4f42882c-2831-96da-a38b-20ed55fe1fd7.jpeg" width="50%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/bb1d857a-bc5c-cd97-daee-c5645e030a53.jpeg" width="50%">

これで表示のON/OFFができました。

# おわりに

これで、表示のON/OFFができました。
今の状態は、持ち運ぶことはできますが、実は手に装着状態では板が追従してくれません。
そこで、明日は手に装着しているときも追従して、でも手で持っているときは手で持っている方に追従するようにコードを書き換えていこうと思います。