簡単なメタバースを作ってみた
この記事は Unityゲーム開発者ギルド Advent Calendar 2022 12日目の記事です。
目次
はじめに
「メタバース」という新語が2022年になってインターネット上でよく使われるようになりました。新語ゆえに定義ははっきりしておらず、「NFTや仮想通貨のやりとりがあるか」「VR機器に対応しているか」「雇用があるか」などの要素によってメタバースなのか否かなのかが随所で議論されています。いずれにせよ「オンラインで自身を操作でき、かつ他のプレイヤーとのコミュニケーションが取れるCG空間」というとは共通のようです。VRChatやcluster、NeosVR、VirtualCastなどのVRSNSはもちろん、『あつまれどうぶつの森』『Minecraft』などのオンラインゲームもメタバースと言えます。
なので今回は「オンラインで自身を操作でき、かつ他のプレイヤーとのコミュニケーションが取れるCG空間」を、Unityを用いて作りたいと思います。
実際にUnityでメタバースを作ってみる
2022年12月12日現在、このメタバースは開発中なので、最小限となっております。
Unityプロジェクトを作成する
何がともあれ、Unityプロジェクトを作成しなければ何も始まりません。
今回は、Unity 2022.1.23f1で、標準のBuilt-in Render Pipeline搭載の3Dで作りました。
Photon Fusionでオンライン共有する
早速、メタバースのコアな部分となる「オンライン同期」ですが、2022年12月12日現在、『Photon』という非常に便利なサービスが存在します。よって今回はPhotonを使ってオンライン同期を行いたいと思います。
Unityで扱えるPhotonには、従来の『Photon Unity Networking 2(PUN2)』と、その後継の『Photon Fusion』があります。
Photon公式は「後継となる『Photon Fusion』を使ってね!」と告げているので、Photon Fusionを採用しました。なお、Photon Fusionはリリースしてから間もないので、従来のPUN2と比較すると遥かに情報量は少なく、導入や運用には苦労することもあります。(後日、Photon Fusionの使い方の記事も執筆したいと思います)
『Photon Fusion』は、Photon公式サイトよりSDKとして提供されており、unitypackageとしてダウンロードできます。
Photon Fusion SDK ダウンロードサイト(Photon公式、日本語)
ちなみに、Photon Fusionを利用するにはクラウドが必要となります。Photon公式のダッシュボードより、Photon Fusionのクラウドアプリケーションを作成する必要がございます。20CCU(同時接続上限人数が20)ならば、無料で利用できます。
注:Photonアカウントが必要です。
Photon Voiceでボイスチャットを可能にする
Photonはまた『Photon Voice』という、ボイスチャット機能を簡単に実装できる便利なモジュールを提供しています。
Photon Voiceはアセットストアからの無償提供となっております。
Photon Voice 2(Unity Assets Store)
そして、Photon Voiceを使用するには、Photonのクラウドアプリケーションが必要となります。よって、ダッシュボードからVoiceのクラウドアプリケーションを生成します。
Photon Voiceの詳しい使い方は後日、別記事にて解説する予定です。その間、Photon公式のドキュメントが役に立ちます。
Photon Chatを追加導入してテキストチャット機能を作成する
Photonはまたまた『Photon Chat』という、テキストチャット機能を簡単に実装できる、これまた便利なモジュールを提供しています。
Photon ChatもUnity Assets Storeからの無償提供となっております。
Photon Chat(Unity Assets Store)
Photon Chatを導入する際にも、PhotonのダッシュボードからChatのクラウドアプリケーションを生成し、IDを取得します。
Photon Chatの詳しい使い方も後日、別記事にて解説する予定です。その間、Photon公式のドキュメントが役に立ちます。
ただ、動作させるのに_chatClient.Service()を定期的に呼び出す必要があったのに苦労しました。なのでこの部分だけは、シェアしたいと思います。
public class ChatManager : MonoBehaviour, IChatClientListener
{
// インターフェース定義メソッドは省略
private ChatClient _chatClient;
private void Awake()
{
_chatClient = new ChatClient(this)
{
ChatRegion = "ASIA"
};
}
// これがなければ動作しない。
private void Update()
{
_chatClient.Service();
}
}
アバターにはVRMを用いる
VRMはVRアプリケーション向けに規格化された、Humanoid基準のボーンが搭載された3Dモデルのファイルです。
VRMファイルは、clusterやVirtual CastなどのVRSNSで採用されています。よって、当アプリケーションもVRMファイルを採用しました。
また、VRMファイルの作成にはVRoidStudioというツールが便利です。WindowsとMacOS(Appleシリコン対応)の両方で動作し、料金は無料です。
VRMファイルの読み込みを可能にする
さて、VRMファイルの解説を行ったところで、VRMファイルをUnityに取り込む必要がございます。
そんな時に重宝するのが『UniVRM』です。UniVRMを導入することによって、Unity上でVRMファイルの操作を行えるようになります。
UniVRMは、以下のGitHubページよりunitypackageとして無償ダウンロードできます。
また、vrm1.0は普及しておりませんので、for vrm-0.xの最新版のunitypackageをダウンロードします。
unitypackageを導入した後以下のダイアログが出現しますので「Use recommended Linear」をクリックします。
これにて、VRMファイルの操作準備は完了です。
アバターを同期する
UniVRMの導入によって、VRMファイルのランタイムロードができるようになれば、VRMオブジェクトを同期したいと思います。
だが、ここで、結構厄介な問題が生じます。それは「Photonはランタイムロードされたオブジェクトを同期できない(2022年12月12日時点)」という技術的な制約です。
また、仮にできたとしても、膨大な数のメッシュ情報があるVRMアバターを同期すると通信量も膨大になってしまいます。
ゆえに、VRMアバターを同期するには、以下の工夫が必要となります。
- VRMファイルをアップロード、ランタイムロードできるサーバーを構築する
- Unity側で、オンライン空間にアクセスした時に、全員分のVRMファイルをランタイムロードする
- 位置、回転、アバター変更RPC、エモートRPCなどをPhotonで同期する
- Photonで同期された情報をローカルサイドに読み込まれたVRMオブジェクトにセットする
- 他のプレイヤーがアバターを変更したら、再度サーバーからVRMファイルをランタイムロードする
したがって、VRMファイルをアップロード、ランタイムロードできるサーバーを構築する必要があります。かなり手間がかかりますが、仮に実用的なアプリケーションとしてリリースするのならば、ユーザー情報などのログイン機能も備えたサーバーは必須と言えるでしょう。
今回はRuby on Railsを使って、サーバーを構築しました。このプロセスは非常に長いので、後日記事にしたいと思います。
サーバーを構築したら、UnityWebRequestを用いてVRMファイルをダウンロードし、UniVRMの機能によってVRMオブジェクトを生成します。
アバター移動アニメーションを作る
さて、VRMオブジェクトに動きをつけたいと思います。
VRMファイルからランタイムロードされたVRMオブジェクトにはAnimatorコンポーネントが標準でアタッチされています。Humanoid対応アニメーションを搭載したAnimatorControllerをアタッチすることによって、VRMオブジェクトをアニメーションさせることができます。
ただし、VRMファイルにはAnimatorControllerは存在しませんので、VRMオブジェクト生成時にAnimatorコンポーネントを取得して、外部からAnimatorControllerを代入します。
アバターの移動アニメーションは、以下のUnity-Chan! Modelのアセットに含まれているアニメーションファイルを利用しました。
Unity-Chan! Model(Unity Assets Store)
そして、VRMオブジェクトはPhotonで同期されていないので、RPCによってローカルに反映させます。
エモート機能を搭載する
VRMファイルは、Skinned Mesh Renderer というBlend Shapeが設定できるメッシュがあり、そのBlend Shapeの値を変更することによって、メッシュの形状を変更することができます。
便利なことに、VRMオブジェクトには『VRM Blend Shape Proxy』というコンポーネントが標準でアタッチされており、このコンポーネントを用いることによって、簡単に複数のBlendShapeプロパティを変更することができます。
public void Emote(BlendShapePreset preset)
{
// blendShapeProxyはVRMBlendShapeProxy型のインスタンス変数
blendShapeProxy.ImmediatelySetValue(BlendShapeKey.CreateFromPreset(preset), 1.0f);
}
アニメーションと同様、VRMオブジェクトはPhotonで同期されていませんので、RPCでローカルに反映させます。
さいごに
2022年12月12日現在、このメタバースは開発中なので、今後とも機能を追加したいと思います。アドカレの記事なので、拙速主義となってしまいましたが、最後まで読んでいただいた読者様には感謝いたします。テキストばかりで読みにくかったかもしれませんが、メタバース開発のヒントになれば幸いです。
それでは、よき創作ライフを!
・・・イーサリアムブロックチェーンを参照して、NFTと関連づけることは多分行わないと思います。