バーチャルキャストのVCIスクリプトの例

# この記事について
VirtualCastでアイテムや背景の機能を拡張できるVCIスクリプトを適当に試したことのメモです。
間違いなどがあったら教えてください。

VirtualCast: https://virtualcast.jp/ 
公式wikiのVCIのページ: https://virtualcast.jp/wiki/doku.php?id=モデル作成:vci作成

現在のバージョン(1.5.0b)での動作に基づきます。バージョンアップですぐに役に立たなくなる可能性が大きいです。


## サブアイテムの操作
`vci.assets.GetSubItem("アイテム名")`でサブアイテムを取得できる。取得したサブアイテムに対して操作する。

```lua:Subitem1の位置を原点に戻す
local SubItem = vci.assets.GetSubItem("Subitem1")
SubItem.SetPosition(Vector3.__new(0,0,0))
```

```lua:アイテムをy軸回転させる
local SubItem1 = vci.assets.GetSubItem("Subitem1")

---アイテムを生成したユーザーで毎フレーム呼ばれる
function update()
    local rotation = SubItem1.GetLocalRotation()
    local rotateSpeed = Quaternion.Euler(0, 3, 0)
    SubItem1.SetLocalRotation(rotation * rotateSpeed)
end
```

## イベント関数での操作
アイテムをつかんだときなどに実行したいスクリプトはイベント関数の中に書く。

```lua:重力オフのアイテムを離すとどこかに飛んでいくのを防ぐ
---[SubItemの所有権]アイテムをUngrabしたときに呼ばれる。
---@param target string @UngrabされたSubItem名
function onUngrab(target)
    local SubItem = vci.assets.GetSubItem(target)
    SubItem.SetVelocity(Vector3.__new(0, 0, 0))
    SubItem.SetAngularVelocity(Vector3.__new(0, 0, 0))
end
```

```lua:モデルや他のアイテムに衝突しても飛んでいかないようにする
---[SubItemの所有権]アイテムにCollider(not Trigger)が離れたときに呼ばれる。
---@param item string @SubItem名
---@param hit string @Collider名
function onCollisionExit(item, hit)
    local SubItem = vci.assets.GetSubItem(item)
    SubItem.SetVelocity(Vector3.__new(0, 0, 0))
    SubItem.SetAngularVelocity(Vector3.__new(0, 0, 0))
end
```

```lua:グリップを押したとき前方向に飛ばす
---[SubItemの所有権]アイテムをグラッブしてグリップボタンを押すと呼ばれる。
---@param use string @押されたアイテムのSubItem名
function onUse(use)
    local SubItem = vci.assets.GetSubItem(use)
    local forward = SubItem.GetForward()
    SubItem.AddForce(forward * 1000);
end
```

`math.random()`で0から1のランダムな数字を得られる。

```lua:グリップボタンを押したときにマテリアルの色をランダムに変える
---[SubItemの所有権]アイテムをグラッブしてグリップボタンを押すと呼ばれる。
---@param use string @押されたアイテムのSubItem名
function onUse(use)
    local r = math.random()
    local g = math.random()
    local b = math.random()
    vci.assets._ALL_SetMaterialColorFromIndex(0, Color.__new(r, g, b))
end
```

## 他のプレイヤーとの同期
`vci.studio.shared.Set`で他のプレイヤーに対して値を送信する。
`vci.studio.shared.Bind`で値を受信したときの関数を登録する。

```lua:30フレームごとにスケールを0.5～0.7にランダムに変更する
local SubItem1 = vci.assets.GetSubItem("Subitem1")

---アイテムを生成したユーザーで毎フレーム呼ばれる
function update()
    if (vci.me.FrameCount % 30 == 0) then
        local scale = math.random() *0.2 + 0.5

        -- "Scale"と言う名前でscaleの値を送る
        vci.studio.shared.Set("Scale", scale)
    end
end

-- "Scale"と言う名前で値が送られてきたときに呼ばれる。
---@param value number @送られてきた数値
function onScaleChanged(value)
    SubItem1.SetLocalScale(Vector3.__new(value, value, value))
end

-- "Scale"と言う名前で値が送られてきたときにonScaleChangedが呼ばれるように登録する
vci.studio.shared.Bind("Scale", onScaleChanged)
```

## 自動的に同期される関数
`_ALL_SetMaterialColorFromIndex`のように`_ALL_`から始まる関数は自動的に他のプレイヤーと同期される。

```lua:グリップボタンを押したときにマテリアルの色をランダムに変える
---[SubItemの所有権]アイテムをグラッブしてグリップボタンを押すと呼ばれる。
---@param use string @押されたアイテムのSubItem名
function onUse(use)
    local r = math.random()
    local g = math.random()
    local b = math.random()
    vci.assets._ALL_SetMaterialColorFromIndex(0, Color.__new(r, g, b))
end

```

`_ALL_`がつかないバージョンを使うと自分の画面だけでマテリアルの色を変えられる。

```lua:グリップボタンを押したときにマテリアルの色をランダムに変える
---[SubItemの所有権]アイテムをグラッブしてグリップボタンを押すと呼ばれる。
---@param use string @押されたアイテムのSubItem名
function onUse(use)
    local r = math.random()
    local g = math.random()
    local b = math.random()
    vci.assets.SetMaterialColorFromIndex(0, Color.__new(r, g, b))
end
```