基礎から始めるVket Cloudワールド作成

## はじめに
この記事は [VR法人HIKKY Advent Calendar 2023](https://qiita.com/advent-calendar/2023/hikky) の21日目の記事です。
前日は[リモートピザを巡る冒険](https://magazine.vket.com/n/n08d3edcbf2f9)でした。🍕🎉🍕🎉🍕🎉🍕🎉🍕


## これはなに
　Vket Cloudで初めてワールドを作成しようとした時に、引っかかってしまうような仕様を、基本的な概念から説明した記事です。あくまで、Vket Cloudのワールドがどのように成り立っているかを説明しているため、より実践的なワールド作成方法などについては、[VketCloudSDK Manual](https://vrhikky.github.io/VketCloudSDK_Documents/latest/ja/index.html)や、[note](https://magazine.vket.com/m/m166a0a5e6a37)をご参照ください。

## Vket Cloudの基礎

### そもそもVket Cloudって？
　Vket Cloudとは、PCやスマホでアクセス可能なメタバースを作成できる開発エンジンです。Webブラウザのみで動作可能で、Webサイトの基本的な仕組みと、ゲームエンジンの仕組みを組み合わせることで、WebAPIの仕組みを使いながら、メタバースのワールドに必要な様々な機能実装を可能としています。

　Vket Cloudのコアは独自に開発されたゲームエンジンであるVket Cloudエンジンであり、このエンジンに含まれるレンダリングパイプラインはUnityのBuilt-in Render Pipelineと似た見た目ですが、Vket Cloud独自の描画エンジンです。

　また、これに限らずVket CloudとUnityは見た目が似ているだけで、根本的な考え方に多くの違いがあるため、別の仕組みで動いているモノと考えたほうが、Vket Cloudでギミックや機能を作成する時や、何かの問題が発生した時の問題解決に役立ちます。<br>
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/12118f00-7fde-42ae-a3db-65ecc2f65794.png)

### Vket Cloud SDKって？
　Vket Cloud SDKはVket Cloudのワールドを作成するためのUnityのエディタ拡張で作成されたツールキットです。
　Vket Cloudに用意された機能を、Vket Cloud SDKがUnity上で表現できるようにして、Vket Cloudのワールド用にリソースをビルドしています。
　実は、Vket Cloudのワールドは、Vket Cloud SDKを介さずに作成自体は可能であり、後述するscene.jsonを適切に記述したりすれば、ワールドのアップロードはできませんが、ローカル環境での作成自体は可能です。
　※Unityのsceneファイルは手書きで記述できます…。と言っているのと同様レベルの意味合いにはなりますが…。<br>
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/b040d20b-fb6d-2d5c-bf38-25477610d21f.png)



### Vket Cloudのワールドの構造

#### scene.jsonについて
　Vket Cloudはscene.jsonと呼ばれるjsonファイルによって、各リソースの読み込みや管理が行われています。

<details>
<summary>scene.jsonを確認するには？</summary>

1. ワールドを作成して、VketCloudSDK > Build And Runをクリック
2. 立ち上がったコマンドプロンプトや、ブラウザのタブは閉じる
3. VketCloudSDK > Open Release Folderをクリックし、ビルドされたリソースフォルダを開く
4. release\data\Sceneフォルダ配下に移動
5. ビルドしたワールドのシーンのjsonファイルが確認（jsonファイルの名前は場合によります）
</details>

　このscene.jsonをいろんなものを割愛しつつざっくりと記載すると、以下のような構成となっています。ワールドの初期設定や、カメラやレンダリング、プリセットアバターのvrmや、モーション等、Vket Cloudのユーザーが変更可能なほぼすべての要素が記載されており、Vket Cloudのバージョンによって記載できる内容は異なります。

```scene.json
{
  "version": 0,
  "debugmode": false,
  "useavatarclick": true,
  "その他いろんな設定": trueとかfalseとか,
  "camera": {
    "いろんな設定"
  },
  "avatars": {
    "いろんな設定"
  },
  "myavatar": {
    "いろんな設定"
  },
  "items": [
    "いろんな設定"
  ]
}
```

#### 3Dモデルの独自規格【.heo】について
　Vket Cloudには.heoという独自の3Dモデルの規格が存在します。
 
　特徴を2点ほど上げると、
1. **heoファイルは、Unity上で配置した複数のオブジェクトを一つのファイルとしてパックします**（テクスチャは別ファイルのままです）
パックされた一つ一つの3DモデルはUnityで設定した各オブジェクトの名前のまま書き出され、**node**として管理されます。
2. **nodeは階層構造を持っていません。**
よって、Unity上で階層構造を持っていたとしても、heoとして書き出した後は、一列に並んでおり、Unity上では親だったGameObjectを選択して表示非表示などの動作を行ったとしても、Vket Cloud上では親子関係はなくなっているので、もともと子だった要素に対して、表示非表示は動作しません。

　.heoファイルを書き出すには、

* シーン上にHEO FieldコンポーネントをつけたGameObjectを配置し、そのGameObject配下に、書き出したいモデルやコライダーを設置して、VketCloudSDK > Build And Runを行う。
* シーン上にGameObjectを配置し、そのGameObject配下に、書き出したいモデルやコライダーを設置して、親となったGameObjectを選択し、UnityのメニューのVketCloudSDK > Export Fieldを行う。

ことで書き出しを行うことができます。<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/8418c98d-791f-1cf7-ae74-59eec67d837e.png)


### 意識すべき要素
　Vket CloudがUnityの構造とは違い、scene.jsonによって配置されるものが変わる。heoという独自規格がある。という事をわかった上で、それが何の役に立つのかという話になりますが、Vket Cloudでのギミック制作において、自分が操作したいものがscene.json上のどの要素なのか、はたまた.heo内のnodeなのかという事を意識しないと、
 
 * モノを動かしたいのに動かせない…。
 * 表示、非表示を操作したいのに正しく動作しない…。
 * どうやったらこのオブジェクトを取得できるかわからない…。

という事が発生します。
　以下に、ギミック、機能制作で特に意識したほうがいいscene.jsonの要素について説明します。<br>
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/145f2ab4-55d7-71c8-4f36-1e17743f2bc4.png)

#### items
　itemsとは、itemと呼ばれるグループの集まりであり、シーン上に配置されているモデル、コライダー、サウンド、パーティクルなど様々な要素はすべてitemsとして登録されます。
　itemsを構成するitemは、Vket Cloud SDKによって追加された、HEO Field、HEO Objectといったコンポーネントを持つゲームオブジェクトを配置、設定することで出力することが可能です。
 
　itemにはtypeという要素があり、typeによって、そのitemの役割が決まります。
　typeは十数種類あり、いくつか例に挙げると、
* fieldタイプのitemであれば、設置された位置を動かせないもの。
* objectタイプのitemであれば、位置を動かしたり、Animationを行えるもの。
* planeタイプのitemであれば、画像を配置できるもの。
* textplaneタイプのitemであれば、文字入力ができるもの。
* cameraタイプのitemであれば、演出目的等で通常のカメラから切り替えるためのもの。
* bgm, se, systemタイプのitemであれば、サウンドの再生に使用するもの。
* particleタイプのitemであれば、パーティクルの再生に使用するもの。

というように振舞います。<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/7e96454a-8015-7987-f7d8-3f93c64ebe6b.png)


#### field
　fieldタイプのitemは、scene.json上の設置された位置から動かせません。そのため、scriptを使用して、fieldタイプのitemを取得して動かそうとしても、微動だにしません…。その代わりに、nodeに対しての操作が豊富に行えたり、Unity上での編集が簡単に行えます。
　動かない地形などについては、fieldとして設置しましょう。

　fieldとしてオブジェクトを設置するには、
1. HEO Fieldコンポーネントを持つゲームオブジェクトをUnityのシーン上に設置。
2. 設置したゲームオブジェクトの子に3Dモデルやコライダーを配置する。

そうすることで、ビルド時にheoファイルとしてパックされ、scene.json上にfieldタイプのitemとして登録されます。

#### object
　fieldと同じく3Dモデルを配置するためのtypeとしてobjectがあります。objectタイプのitemは、fieldと違って移動、回転、スケールの変更がスクリプトによって変更できたり、さらに、ボーンアニメーションを含むアニメーションが使用できたりします。ただ、書き出しまでの手順が少し複雑なので、何度も微調整が必要なものに関してはfieldにしておいた方が楽かもしれません。
　動くモノや、scriptによる複雑な動作をさせたいモノに関しては、objectとして設置しましょう。

　objectとしてオブジェクトを設置するには、
1. objectとして設定したいゲームオブジェクトを選択（複数選択は不可）
2. VketCloudSDK > Export Fieldを行う。
3. heoファイルの保存場所を設定し書き出す。
4. HEO Objectコンポーネントを持つゲームオブジェクトをUnityのシーン上に配置する
5. 書き出したheoをHEO Objectに設定する。

そうすることで、ビルド時に設定されたheoファイルが任意の場所にコピーされ、scene.json上にobjectタイプのitemとして登録されます。

※また、わかりづらい要素として、Avatarのボーンに対して追従するモノについてもObjectという名称になっています。
Action Triggerで設定できるShow/HideObjectのObjectはこのAvatarに設定できるObjectのことを指します。

### Vket Cloudの基礎まとめ
Vket Cloudでの機能制作の際は、今自分が操作したい対象が、itemなのか、itemでもtypeはobjectなのか、fieldなのか。別のtypeを持つitemなのか。はたまた、.heo内にあるnodeなのか。それらを意識することが重要です。
なんだかよくわからないけど、動作しない…。というときはどのようにしてそれがシーン上に配置されているかを確認してみましょう。<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/f1d9a279-b27b-c873-4f9b-917a9e6a38c9.png)


## Vket Cloudでわかりづらい要素

### 同じ名前のGameObjectは非推奨
Vket Cloudでは名前によって操作したいモノを取得して、何かの動作を行うことがほとんどです。特にscene.json内に記述されたitemは、Unityのguidのようなものを持たず、名前によって管理されているため、同じ名前のitemがscene上に配置されていると、正しくギミックが動作しないことがあります。

itemとして設置するモノに関しては、必ず別の名前を設定するように心掛け、.heoとして書き出されたnodeに関しても、スクリプトやAction Triggerによって操作するものに関しては、名前を変更しましょう。<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/3fbb6e76-686a-bd2d-fbd4-aecb72b38367.png)


### Render QueueはHierarchy上の順番によって決まる。
Unityで半透明のオブジェクト設置したものの、うまく描画の前後関係をコントロールできないとき、MaterialごとのRender Queueを大きくしたり、小さくしたりすることでコントロールすると思います。

しかし、Vket Cloudでは、MaterialのRender Queueによって描画順を設定しているわけではなく、Hierarchy上の順番によって、描画の優先順位が決まっています。

Hierarchyの順番の下に配置されるほど、描画の順番が後ろになるため正しく描画結果が描きこまれます。

もし、半透明オブジェクトの描画順が気になるときは、Hierarchyの順番を調整してみましょう。<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/b3077f30-3610-e832-b197-205698ced0e7.png)


### オブジェクトを動かす
前述したとおり、fieldタイプのitemは動かすことができません。また、.heoとして固められたnodeについても.heoとして固めてしまっているため動かすことができません。
なので、動かしたり、アニメーションさせたいモノはobjectタイプのitemとして設定しましょう。<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629942/5e36b0f8-aabe-214c-976b-97bfb4a90f07.png)

## 最後に
Vket Cloudのワールドの成り立ちや仕組みを理解すると、ワールドを作成するときにどのような作業が必要なのかを考えることができ、やってみたけどできなかった…。よくわからない…。という事を回避することができます。

座学的なところが多く、読むのが大変な記事になってしまいましたが、よりよいワールド作成に役立てることができれば幸いです！

ここまでお読みいただきありがとうございました！

明日のアドベントカレンダーは、
@negi_trotsky さんのVketCloudSDKを触ってマニュアルを見てついでに加筆して欲しいというはなしです。

Icons by [Icons8](https://icons8.com/)