見出し画像

ゼロから始めるメタバース開発基礎講座

こんにちは。REALITY株式会社GREE VR Studio Laboratory(ラボ)インターンの角田です。今回の記事では、ラボで開催予定の「メタバース開発もくもく会」の準備を兼ねて、メタバース開発の基礎についてお伝えします。

あわせてこちらの動画「140秒でわかるメタバース開発TIPS」もご参照下さい!
<動画プレイリスト> https://bit.ly/140meta


はじめに

今回のこのブログでは「この春からメタバース開発を学び始めてみたいな…」という学生さんや新社会人向けのチュートリアルを作ってみました。無料で使えるGitHub、Unity、VRMを利用して複数のプレイヤーがメタバース内でいろいろコミュニケーションできるアプリケーションを開発するうえでの最初のきっかけになれば幸いです。

開発環境

GitHubでデータ管理

Unity環境に限らずチーム開発するときによく使われるコード共有サービスが、GitHubです。GitHubとは、コードのバージョンを管理するシステムGitを使用したプラットフォームであり、個人だけでなく企業や大学の研究開発でも使用されています。
GitHubではリポジトリ(図1)と呼ばれる保管場所をプロジェクトごとに作成し、そこに各メンバーが作ったコードやファイル、フォルダーで保存します。リポジトリにコミットという操作を実行すると、リポジトリの開発状況を更新できます。更新された内容はGitHub上で確認できます。作業がひと段落するたびにこまめにコミットするのがおすすめです。

図1. GitHub上でのリポジトリの中身(修行中)

プログラムを書いている途中で、「現状の状態を残しつつ、新しく機能を追加・バグの修正をしたい!」というときがあると思います。このときに有効なのがブランチです。ブランチとは、開発中のコードから分岐して別の環境で作業を行い、本体に影響を与えずに開発を進める機能です。幹から枝を伸ばすようなイメージで作ります。mainブランチは、正常な動作をするバージョンのみを更新します。新しい作業を進める場合はブランチを作成し、そこにバージョンを更新していきます。完了した作業をmainブランチに統合したい場合、作業者はプルリクエスト(PR)という操作を行い、プロジェクトのマネージャーにコードレビューを依頼できます。マネージャーがコードを確認し、問題がなければブランチをmainブランチに統合します。こうすることで、mainブランチは常に確実に動く状態を維持したまま新機能や実験的な機能を開発していくことができます(実際のチームや開発スタイルによって異なります)。
バグや追加したい機能が開発中に出てきた場合、Issueを作ることで改善点やバグをチーム間で共有することができます。すなわち、IssueとはToDoリストのようなものです。また、Issueを作成する際に担当者を割り振れるので、タスクの管理が容易になります。修正したブランチをIssueとともにコードレビュー者にPRし、それをテストしMainに回収し…と、イテレーションを繰り返すことによって、チーム開発を円滑に進められます。また、GitHubで作業を続けると、プロフィールにコミットメント(貢献)が可視化されます(図2)。皆さんも、チーム間での開発でたくさん作業し、プロジェクトに貢献しましょう!

図2. GitHubのプロフィール上で表示される。通称「草が生える」状態。

VRMアバター

メタバース開発で、3Dアバターを利用する際に便利なのがVRMです。VRMとは、人型の3Dアバターを1つのデータにまとめたオープンなファイルフォーマットのことです(図3)。プラットフォームに依存しないで使用でき、ライセンス情報などアバター特有のデータも含められます。また、VRMの最大のメリットは、Unity等でのアバター読み込みが容易にできるという点です。この章ではVRMアバターの読み込み方、アニメーションの適用方法ついて説明します。それでは、実際に手を動かしていきましょう。

図3. VRMコンソーシアムによる「VRMアバターについて」(引用)

VRMファイルの読み込み方

まず、VRMの読み方についてです。VRMには0系と1系の2つのバージョンが存在します。これら2つではアバターの読み込み方が異なります。この節ではロードが容易なVRM1系を用いて説明します。手順は以下の通りです。こちらの内容は140秒動画「VRMアバターをスクリプトから読み込んでみよう
」でも解説しているので、チェックしてみてください。

①UniVRMのパッケージをダウンロード
UniVRMというVRMを操作できるプラグインをインポートする。UniVRMのGitHubのページに移り、最新バージョンのUnityPackageをダウンロードする。ただし、VRM 1.0を選択すること(図4)。

図4. UniVRMのUnityPackageダウンロード画面

②UniVRMのインポート
Assets→Import Package→Custom Package(図5)からダウンロードしたUnityPackageをインポートする。

図5. UnityPackageのインポート方法

③UnityProject内にVRMファイルを保存
用意したVRMファイル(ここでは、Student.vrm)をUnity内のStreamingAssetsフォルダに格納する(図6)。Assets内にStreamingAssetsがない場合は自分で作成。

図6. VRMをStreamingAssetsに保存

④コードの作成
VRMファイルを読み込むスクリプトを作成する。Assets内にScriptsフォルダを作成し、Scriptsフォルダ内で右クリックして、Create→C# Scriptでスクリプトを作成。スクリプト名をVRMLoader.csとし、以下のようにコードを組む。

using System;
using UnityEngine;
using UniVRM10; //VRM1系を扱うための名前空間
public class VRMLoader : MonoBehaviour {
    [SerializeField] string _vrmName; //VRMファイル名
    private void Start() { //StreamingAssetsフォルダ内のVRMファイルを読み込む 。InspectorでVRMファイル名の記入を忘れない。
        string _vrmPath = $"{Application.streamingAssetsPath}/{_vrmName}.vrm";
        VRMLoadAsync(_vrmPath);
    }
    private async void VRMLoadAsync(string path) {
        try { //VRM1.0ファイルの非同期読み込み(失敗した時を考慮)
            await Vrm10.LoadPathAsync(path);
        } catch (Exception e) { //読み込みに失敗した場合の例外処理
            Debug.LogError("Failed to load");
            Debug.LogException(e);
            throw;
        }
    }
}

⑤実行
Hierarhyを右クリックして→Create Emptyして、空のオブジェクトを生成。そのオブジェクトを選択した状態のまま、右側のInspectorでVRMLoader.csをAddComponent(オブジェクトに機能を追加する操作)する(図7)。用意したVRMファイルの名前を記入し、UnityEditor上の再生ボタンを押す。

図7. 空のオブジェクトにVRMLoader.csをAddComponentした状態

⑥VRMファイルの読み込みに成功
再生ボタンを押した後、スクリプトが実行され、以下のようにVRMアバターが読み込まれる(図8)。

図8. VRMアバターの読み込みに成功した様子

VRMアバターをアニメーションで動かす

①アニメーションの準備

次に、VRMアバターにアニメーションで動きをつけさせます。VRMアバターに特定のアニメーションの動きをさせるためには、VRMアバターを動かすAnimationファイル(.anim)を用意する必要があります(例えばBoothのこちらなどで配布されている方がいらっしゃいますので探してみてください)。実際にVRMアバターをアニメーションファイルで動かしたとき、UnityEditor上では以下のように適用されます(図9)。今回は、VRMアバターをキーボードから操作し、ジャンプ・走る・待機の動作をさせます。

図9. UnityEditor上でのVRMアバターの動き

Adobeアカウントがある方は、Mixamoがおすすめです。左側で欲しいアニメーションを検索し、右側で選択したアニメーションの細かい調整を行います(図10)。アニメーションをダウンロードする際、FPSを60にしておきましょう。ここでは、Mixamo上で走る・ジャンプ・立ち止まるモーションをダウンロードします。

図10. Mixamoの表示画面

Assets内にAnimationsフォルダを作り、ダウンロードしたアニメーションはUnityのAnimationsフォルダ内に保存します(図11)。保存したアニメーションを選択すると、Inspector画面で詳細が表示されます。Animation TypeをHumanoidに変更(図12)してApplyを押すと、アニメーションがVRMアバターに適用されます。AnimationTypeを変更した後、アニメーションファイル(三角のアイコン)を複製し、わかりやすいファイル名に変更しておいてください(図13)。アニメーションファイルを選択し、Loop Timeにチェックを入れます(図14)。これをすべてのアニメーションに対して行います。

図11. Animationsフォルダにアニメーションを保存
図12. アニメーションタイプの変更
図13. Mixamoのデータファイルからアニメーションを抽出
図14. アニメーションファイルのLoop Timeにチェックを入れる

②アニメーションコントローラの設定

次に、アニメーションを動かすためのアニメーションコントローラファイルを作成します。Assets内でResourcesフォルダを作成し、VRMAnimations.controllerという名前のアニメーションコントローラファイルを作成します。VRMアバターに走る・ジャンプをさせるために、以下の遷移状況を用意します(図15)。Idleは待機状態、Jumpはジャンプ状態、Runは走っている状態であり、各ステートにはそれぞれのアニメーションをアタッチしておきます。左側の2つのパラメータ(jump:Trigger型、speed:Float型)はそれぞれIdleからJump、Runの状態に遷移するための条件として使用します。

図15. ステート間の状況

Idle⇔Jump、Idle⇔Runではそれぞれjump、speedパラメータを適用し、アニメーションを自在に制御できるようにします。
IdleとRun間の2つの矢印を選択し、Conditionsからspeedを選択します。Idle→Runではspeedが1より大きいときに遷移させたいため、条件をGreater、数値を1にします(図16)。同様に、Run→Idleではspeedが1より小さいとき、同様に条件をLess、数値を1にします(図17)。また、Has Exit Timeのチェックを外しておきます。

図16. Idle→Runの設定
図17. Run→Idleの設定

IdleとJump間ではIdle→Jumpの矢印のみ選び、Conditionsからjumpを選択します(図18)。また、先ほどと同様にHas Exit Timeのチェックを外しておきます。スクリプト上でjumpがtrueになったとき、ジャンプのアニメーションが再生されます。一方、Jump→Idleは設定を変更しないようにします。

図18. Idle→Jumpの設定

③スクリプトによるアニメーションの制御

Scriptsフォルダ内で新しくスクリプトを作成し、アニメーションコントローラファイルを制御します(Controller.cs)。VRMアバターに以下の操作を実装します。
Wキー:前進
Aキー:左回転
Dキー:右回転
Spaceキー:ジャンプ

Controller.csのスクリプト全体は、以下の通りです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Controller : MonoBehaviour
{
    [SerializeField] float runspeed = 3f; //モデルの移動に関する変数定義
    [SerializeField] float rotateSpeed = 10f;
    private Animator animator; //アニメータに関する変数
    void Start()
    {
        animator = gameObject.GetComponent<Animator>(); //animatorの取得
    }
    void Update()
    { 
        //各種キー操作とアニメーション制御
        if (Input.GetKeyDown(KeyCode.Space) &&
            !animator.GetCurrentAnimatorStateInfo(0).IsName("jump") &&
            !animator.IsInTransition(0))
        { //Spaceキーでジャンプ
            animator.SetTrigger("jump");
        }
        if (Input.GetKey(KeyCode.W))
        { //Wキーで前進
            animator.SetFloat("speed", runspeed);
            animator.transform.position +=
                animator.transform.forward * Time.deltaTime * runspeed;
        }
        if (Input.GetKeyUp(KeyCode.W))
        { //押し終わったらストップ
            animator.SetFloat("speed", 0f);
        }
        if (Input.GetKey(KeyCode.A))
        { //Aキーで左回転
            animator.transform.Rotate(0f, -0.10f * rotateSpeed, 0f);
        }
        if (Input.GetKey(KeyCode.D))
        { //Dキーで右回転
            animator.transform.Rotate(0f, 0.10f * rotateSpeed, 0f);
        }
    }
}

アニメーションを制御している箇所を詳しく見ていきます。アニメーションコントローラのパラメータを制御するとき、型ごとに方法が変わります。

animator.SetFloat(“パラメータ名”, 数値); //Float型 
animator.SetTrigger(“パラメータ名”,true or false); //Trigger型

ただし、animatorはVRMアバターのAnimator Componentであり、Start関数でAnimatorを取得しなければなりません。

スクリプトの冒頭で、走るスピード(runspeed)の定義やVRMアバターのAnimatorを取得しておきます。ただし、runspeedは2.0とします(1.0以上であればIdle→Runの遷移条件を満たす)。
Wキーが押された状態では、

animator.SetFloat(“speed”,runspeed); //24行目

が実行されることでIdle→Runの条件を満たすようになり、VRMアバターはRunステートのアニメーションの動作をします。逆に、Wキーが押されていない状態では、

animator.SetFloat(“speed”,0f); //30行目 

が実行されることでRun→Idleの条件を満たすようになり、VRMアバターのアニメーションはIdleステートに戻ります。
Spaceキーが押されたとき、

animator.SetTrigger(“jump”); //20行目

が実行されることで、Idle→Jumpの条件を満たし、VRMアバターはJumpアニメーションの動きをします。

④カメラの追従

VRMにカメラ追従を行うため、Unityモジュールの1つであるCinemachineをインポートします。Window→PackageManagerを開き、Packages:In ProjectからUnity Registryを選択します。選択後、Cinemachineを探し、Installします(図19)。

図19. CinemachineのInstall

Hierarhy上で右クリックし、Cinemachine→VirtualCameraを選択します。生成されたVirtualCameraを以下のように設定します。

図20. VirtualCameraの設定

⑤VRMLoader.csの修正

Controller.csはVRMアバターにAdd Componentする必要があります。そのため、VRMアバターが読み込まれた後、アバターにController.csをアタッチできるようなプログラムを組みます。VRMLoader.csにVRMAttach関数を新たに追加し、Controller.csのアタッチ、VRMアバターのカメラ追従を行います。VRMLoader.csの全体は、以下の通りです。

using System;
using UnityEngine;
using UniVRM10;  //VRM1系を扱うための名前空間
using Cinemachine; //Unityのカメラを操作するモジュール
public class VRMLoader : MonoBehaviour {
    [SerializeField] string _vrmName; //VRMファイル名
    [SerializeField] CinemachineVirtualCamera _vcam; //カメラ追従ように使うVirtualCamera。使用するVirtualCameraをセットする
    private void Start() { //StreamingAssetsフォルダ内のVRMファイルを読み込む
        string vrmPath = $"{Application.streamingAssetsPath}/{_vrmName}.vrm";
        VRMLoadAsync(vrmPath);
    }
    private async void VRMLoadAsync(string path) {
        try { //VRM1.0ファイルの非同期読み込み
            var vrm10Instance = await Vrm10.LoadPathAsync(path);
            GameObject vrm = vrm10Instance.gameObject; //VRMアバターをオブジェクトとして取得
            VRMAttach(vrm); //VRMAttach関数の実行

        } catch (Exception e) { //読み込みに失敗した場合の例外処理
            Debug.LogError("Failed to load");
            Debug.LogException(e);
            throw;
        }
    }
    private void VRMAttach(GameObject vrm) { 
    //VRMアバターにアニメーションコントローラファイル、Controller.csをアタッチ、カメラを追従
        Animator animator = vrm.GetComponent<Animator>(); //VRMAnimations.controllerを取得
        animator.runtimeAnimatorController = (RuntimeAnimatorController)
            RuntimeAnimatorController.Instantiate(Resources.Load("VRMAnimations"));
        vrm.AddComponent<Controller>(); //Controller.csの追加
        Transform vcamPos = vrm.transform; //virtualcameraの追従
        _vcam.Follow = vcamPos;
        _vcam.LookAt = vcamPos;
    }
}

空のオブジェクトを選択し、Inspector上でVRMLoader.csのVRMアバターの名前、VirtualCameraの設定を行う。Vrm Nameは先ほどと同様”Student”とし、Vcamには作成したVirtualCameraをセットします(図21)。

図21. 空のオブジェクトにVRMLoader.csをAddComponentした状態

以上の操作を行った後、再生ボタンを押すとキーボードでVRMアバターを制御できるようになります(図22)。これでメタバース開発におけるアバター制御の基礎が身につきましたね!

図22. 完成した様子

補足:ここまでの内容はあくまで基礎的なメタバース開発の入門編です(例えばREALITYのアプリを開発するプラットフォーム開発ではVRMやMixamoは使っていません)。実際の開発者として求められるスキルについてはこちらのサイトを見ていただけるとよいと思います(https://corp.gree.net/jp/ja/metaverse-recruit/)。新卒学生さん向けはこちら(https://corp.gree.net/jp/ja/recruit/)。

メタバース開発もくもく会の告知

さて!「メタバース」と一言で言っても、3Dワールドやアバター、クラウドネットワークにアプリ開発など…いきなり高度な開発なんて誰でもできるわけではありませんし、学校で教えるのも難しそうです。そして上記のような入門編も「まずは自分で手を動かしてみないと」わかりません。そこでGREE VR Studio Laboratoryでは毎年開催してきたオンラインハッカソン、「VTechChallenge」(https://vr.gree.net/lab/vtc/)をリニューアルして開催します。「Make it by yourself(メタバースを自分で作る)」を目標に掲げ、参加者はメンターや140秒動画のサポートを受けながら自分のアイデアを実現します。
手始めに、4月20日18時-21時に「メタバース開発もくもく会」を行います!もくもく会のゴール設定は「『メタバースの開発の楽しみ』を最短で学ぶ!」です(図23)。

図23. もくもく会のイメージ画像

参加対象は以下の通りです。

  • 学部学科学年不問(顔、個人情報は非公開OK)、初心者大歓迎、ソロ参加OK

  • メタバースアプリの開発・3Dアバター・Unityなどに興味がある人

  • Unityが動くスペックのPCを持っている人

  • 何か成果物を作りたい人

  • IVRC2023(https://ivrc.net/2023/)に参加したいけど、チームメンバーが集まらないという人

3時間でメタバース開発の基礎を学び、自分のVRMを読み込んで動かすことで「メタバースアプリの開発をやったことがある人」になれます!
ご興味をお持ちの方は、こちらのConnpassのサイトから参加登録をお願いします。

まとめ

今回の記事は、この春メタバース開発に挑戦したい方に向けて、短い時間で習得できる以下の要素について解説しました。

  • GitHubによるプロジェクト管理

  • VRMアバターの読み込み方

  • VRMアバターへのアニメーション適用方法

これらのメタバース開発の基礎を応用し、オリジナルのメタバースアプリを開発してみましょう!

さいごに

改めまして、入社約2か月半の角田です。長文に加えてご挨拶が遅くなりました。去年のIVRC2022において、「適法!日本酒醸造シミュレータ」のチームメンバーとして参加していました。この春から理系の学部4年生となり、半導体ナノデバイスの研究室に配属されました。研究テーマはフォトニクスです。実験が基本となる研究テーマであるので、春から研究主体となって活動していきます。

ラボでは研究開発のお手伝いとともに、ビギナー向けの140秒動画やVTechChallenge2023のお手伝いをさせていただきました。私は基本ハード側で生きてきた人間なのですが、UnityやAdobeなどのソフトウェアに触れ、普段の大学ではできないことを学ばせていただきました。仕事の中では、ソフトウェア開発がハードウェア開発につながる部分を発見できたり、将来を考え直すきっかけにもなりました。また、今回の技術系の記事や140秒動画など、「伝える力」も身に付きました。これは自分にとっていちばんの財産だなと感じています。
この記事が、皆様のメタバースアプリ開発の役に立っていただければ幸いです!
お読みいただきありがとうございました!

REALITY株式会社 GREE VR Studio Laboratoryではメタバース時代のREALITYを開拓すべく日々、新技術の研究開発を推進しています。ご興味がある方は [ラボのWeb](https://vr.gree.net/lab/) やYouTube(https://j.mp/VRSYT)を観ていただけると嬉しいです。
また、インターンに興味を持ってくれた学生さんはぜひ[インターン希望の方へ]やTwitter@VRStudioLabをフォローしてみてください!

追記(5/1):VTechChallenge2023募集開始

学生の皆さんへ!
オンラインでナニモノかになるハッカソン
VTechChallenge2023」を開催中です
エントリーは5/8まで。
腕に覚えがある方も、そうでない方も、ぜひ!