公開したVCIの一部内容(文言等)を利用者がカスタムできるようにする

# はじめに
この記事はVRサービス「VirtualCast」で使用できるVCIという仕組みについて扱った記事です。


# 今回やりたいこと
以前私が作成したVCIに以下のようなビンゴができるものあります。
![2022122223365570.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/751722c2-d536-80ad-948f-7702883d4156.jpeg)
こちらのVCIのコンセプトとして、使用者が自由にビンゴの内容を変更できるようにするということがあります。
今回はそのような一部内容を使用者がカスタマイズできるようなVCIの作り方を紹介します。
(今回紹介する方法は私が考えた方法であり、デファクトスタンダードというわけではありません)

# 使用者がカスタマイズ可能なVCIの作成方法
今回紹介したVCIのように、VCIの一部を利用者にカスタマイズしてもらいたい場合、現在は大きく以下の2通りじつげんほうほうがあるかと思います。
1. VCI配布式：製作者がVCIファイル自体を配布し、使用者がDL後内容を変更した上でSeedにアップロードする。
2. lua修正式：製作者がスクリプトのデバッグを有効にした状態でVCIを公開し、使用者がVCIを取り込んだ上で中のluaファイルを修正する。

大きな違いは __VCIをアップロードするのが使用者になるか製作者になるか__ です
上記それぞれ以下のようなメリットデメリットがあります
|  | メリット | デメリット |
|:--: |--- |--- |
|VCI配布式|・画像などもカスタマイズ可能   | ・提供者側で修正を加えたい場合、修正版VCIを利用者にDLし直してもらう必要がある  |
|lua修正式|・提供者側で修正を加えるのが楽  | ・内容は文字の変更などスクリプトでできる内容のみ<br> ・スクリプトをいじる必要があるため、少しとっつきにくい |

今回は上記のうちlua修正式のやり方を全3STEPに分けて紹介します

:::note
今回はスクリプトを編集する詳細な方法は説明しません。詳細を知りたい場合は公式ページをご覧ください。
:::
:::note warn
今回の方法では作成したVCIのスクリプトファイルが見える状態となります。作成したVCIのスクリプトを公開したくない場合は今回の方法は使用できません
:::

# STEP1：利用者がluaファイル書き換え可能にする
今回作成する方式では利用者にスクリプトファイルを編集してもらう必要があります。
そのためにはアセット情報編集の画面で、「スクリプトのデバッグを有効にする」のチェックボックスを有効にする必要があります
![メタデータの編集.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/61219672-6b20-fc90-bb14-7796408ac244.jpeg)


スクリプトのデバッグを有効にされているVCIを取り込むと、スクリプトのフォルダに以下のように_main.luaというアンダーバー付きのファイルができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/8aad8ec8-ea87-54da-0abf-3d0860c6d423.png)

今回ビンゴ用に実際のコードは以下のような感じです(必要な部分のみ抜粋)
```lua:_main.lua
local Data = {
	--1行目
	"２４時間放送する",
	"凸をする",
	"Vキャスに関する記事を書く",
	"Seedで有料アイテムを購入したことがある",
	"企画に参加する",

    -- 中略

	--5行目
	"twitterの連携が勝手に切れる",
	"Seed Onlineと連携する",
	"アバターの改変をする",
	"凸１６人達成埋まってる現場にいる",
	"InfiniteLoop本社の聖地巡礼",
}

-- パネルに反映
for i=1,25 do
    local text = Data[i]
    vci.assets._ALL_SetText("Text_Panel 1 "..i,text)
end

---以下省略
```

通常はこのアンダーバー付きファイルが読み込まれてスクリプトが動くのですが、以下のようにこのファイルをコピーしてアンダーバー無しのファイルを作成すると、そのスクリプトが読み込まれるようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/ebc43ec8-8a08-de6f-746d-3e361d4b9bab.png)

このコピーしたファイルを書き換えることで内容を変更できます。
今回は食べたことある食べ物ビンゴに変えてみました
```lua:_main.lua
local Data = {
	--1行目
	"猪肉",
	"馬肉",
	"フォアグラ",
	"熊肉",
	"羊肉",

    -- 中略

	--5行目
	"アヒル",
	"いなご",
	"からすみ",
	"海ぶどう",
	"はちのこ",
}

-- パネルに反映
for i=1,25 do
    local text = Data[i]
    vci.assets._ALL_SetText("Text_Panel 1 "..i,text)
end

---以下省略
```
![2022122500094388.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/54b86d91-b17e-767a-cab3-da3090d8071d.jpeg)



まとめると、利用者には以下のような流れで修正してもらうことになります
1. 一度VCIを出す
1. フォルダ内の_main.luaをコピーしてmain.luaを作成する
1. main.luaの中身を変更する



# STEP2：設定ファイルの分離
## STEP1での問題
前章で_main.luaをコピーして内容を変更する方式を説明しましたが、この状態ではVCI作成者が機能追加やバグ修正でスクリプトを修正したい場合に対応ができません
(修正後のVCIを出すと_main.luaは新しいバージョンに変わりますが、main.luaは古いバージョンのまま残ってしまうため古いスクリプトが読み込まれてしまいます)

## 解決方法
上記問題を解決するために、利用者に変更してもらいたい内容だけ抜き出して別ファイルにします。
VCIにはモジュールという概念があり、こちらを使うことでファイルを分けることができます
（詳細は公式ページを御覧ください：https://virtualcast.jp/wiki/vci/script/module）
上記の仕組みを用い、今回はData.luaという名前で設定ファイルを分離します。

```lua:Data.lua
local Data = {
    --1行目
    "２４時間放送する",
    "凸をする",
    "Vキャスに関する記事を書く",
    "Seedで有料アイテムを購入したことがある",
    "企画に参加する",
    
    --- 中略    
    
    --5行目
    "twitterの連携が勝手に切れる",
    "Seed Onlineと連携する",
    "アバターの改変をする",
    "凸１６人達成埋まってる現場にいる",
    "InfiniteLoop本社の聖地巡礼",
}
return Data
```

```lua:main.lua
local Data = require "Data"

-- パネルに反映
for i=1,25 do
    local text = Data[i]
    vci.assets._ALL_SetText("Text_Panel 1 "..i,text)
end

---以下省略
```


このような構成にすることで使用者は以下のように_Data.luaをコピーして作成したData.luaのみ修正すればよくなり、_main.lua側には修正を入れる必要がなくなります。
そのため、製作者がスクリプト(mail.lua側)に修正を加えた場合も最新のコードで動くようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/284da9db-c2d0-af46-3258-0f1efa28f78f.png)

# STEP3:設定ファイルのバージョン管理

## STEP2での問題
前章でスクリプトにバージョンアップがあるときも対応ができるようになりました。
しかし、設定ファイル自体のフォーマットを変えるようなアップデートを加えたいケースでは、この方法だけではたりません。
(_Data.luaは新しくなるがData.luaは変わらないためちゃんと読み込まれない状態になります)

例えば、今回作成したビンゴVCIにタイトルも変更できる機能も入れたいとします。
その場合、Data.luaにはタイトルの項目がないため項目を追加する必要があります。
現状のDataでは直下にビンゴの内容が書かれており項目追加ができなかったため、以下のようにフォーマットを変更することにしました。

```lua:Data.lua
local Data = {
	-- ここにビンゴタイトルを入れる
	TITLE = "食べたことあるもの",
	-- ここにビンゴの各マスに表示する文字を入れる
	TEXT_LIST = {
        --略：ビンゴに表示する内容
	}
}
return Data
```

上記のようにData.luaのフォーマットを修正した場合、スクリプト側のビンゴの内容を読み込む箇所にもData.TEXT_LISTから読み込むように製作者の方で変更をかけることになります。
しかし、使用者が古いフォーマットのData.luaを使っている場合、TEXT_LISTという項目がないため取得が正しくできずエラーとなってしまいます。


これはファイルをいくら分割しても消えない問題のため、古いバージョンを使っている方に新しいバージョンのフォーマットをベースに書き直してもらう必要があります。
しかし、通常は利用者はフォーマットが変わっていることに気づけない状態なので、なんらかの方法でData.luaの書き換えが必要な旨を伝えなければなりません。

## 解決方法
今回は上記課題を以下のような方式で解決します
　・Data.luaとmain.luaにそれぞれ同じとなるようにバージョン情報を持たせる
　・VCI起動時にData.luaとmain.luaのバージョン情報を比較する。
　　このとき、Data.luaがあればそちらの、なければ_Data.luaのバージョン情報が読まれる。
　・Data.luaのバージョンが古い場合に利用者に変更を促すメッセージを表示する
このようにすることでフォーマットが変わった際に、Data.luaとmain.luaのバージョン情報をアップデートするだけで利用者への変更を促すメッセージを出すことができます。
(私が考えたオリジナルの方法になるので、他にいい方法があるかもしれません)

以降、具体的な手順を説明していきます。

まずは利用者に伝える用の表示オブジェクトを作ります。
こちらは後述のスクリプトで普段は見えないようにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/e0671702-cc7a-4066-83a7-087a6238e2a0.png)

次にluaファイルに以下の修正を加えます。
　・mina.lua、Data.luaそれぞれにバージョン情報の追加
　・バージョン情報を比較し、変更を促すメッセージの表示/非表示を切り替える処理の追加

```lua:Data.lua
local Data = {
	VERSION = 1.0,
	-- ここにビンゴタイトルを入れる
	TITLE = "食べたことあるもの",
	-- ここにビンゴの各マスに表示する文字を入れる
	TEXT_LIST = {
        --略：ビンゴに表示する内容
	}
}
return Data
```

```lua:main.lua
local Data = require "Data"
local VERSION = 1.0

local versionAlert = vci.assets.GetTransform("VersionAlert")
-- Data.luaとのバージョン差分があるか確認
if Data.VERSION and Data.VERSION >= VERSION then
  versionAlert._ALL_SetActive(false)
else
  versionAlert._ALL_SetActive(true)
  --強制的に処理終了
  return 
end

-- パネルに反映
for i=1,25 do
    local text = Data.TEXT_LIST[i]
    vci.assets._ALL_SetText("Text_Panel 1 "..i,text)
end
vci.assets._ALL_SetText("Text_Title",Data.TITLE)

---以下省略
```


実際に設定ファイルのバージョンを変えたい場合はスクリプト内のバージョンを変更します
すると以下のように警告メッセージが表示され、使用者が差し替えが必要なことに気づくことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/d3d33cef-1280-c3f6-a35d-9b47d249a372.png)



# まとめと課題
今回はファイルを別にする&バージョン管理をすることで使用者が内容を変更可能なVCIの作成方法を紹介しました。
今回は文言の変更ベースではなしをしましたが、設定値などを外だしすることで挙動を帰ることもできます。

ただ、この方法では自分の作成したスクリプトも公開しないと行けないというデメリットが残ります。
上記の問題はVCIを配布する方法でも同様であり、スクリプトの内容を隠しつつ使用者が内容変更が可能なVCIを作る方法はおそらく今のVCIでは存在しないかと思います。
そのため、何らか使用者が変更可能な設定型項目ができることを切に望んでいます。