土鍋で雑多煮

UnityでXR・ゲーム開発をしています。学んだことや備忘録、趣味の記録などを書いていきます。

MENU

Netcode for GameobjectsでVRマルチプレイゲームを作る

はじめに

どうも、土鍋です。

今までVRマルチプレイゲームを作る際、まともなチュートリアルが少なかったため、なかなかハードルが高かった。が、今年、Metaが公式の記事とBuilding Blocksにマルチプレイ用のものを追加した。

Photon FusionによるVRマルチプレイの実装はたまに見かけるので、今回はNetcode for Gameobjectsを使ってやってみた。

Meta公式記事

https://developers.meta.com/horizon/documentation/unity/bb-multiplayer-blocks

VRマルチプレイの準備

Metaのライブラリのインポート

いつものMetaのアセットをインポート

Netcode for Gameobjectsのインポート

Auto Matchmakingを使用するには以下のライブラリが必要だ。

Unity Netcode for Game Objects: com.unity.netcode.gameobjects
Unity Service Relay: com.unity.services.relay
Unity Service Lobby: com.unity.services.lobby

これらはAdd package by nameでインポートする。

Building Blocks

ネットワーク関連のBuilding Blocksが最近追加された。

Auto Matchmakingを追加する。今回はNetcode for Gameobjectsを使用する。

もろもろ追加してヒエラルキーは以下のような感じ。

プレイヤーの同期

ひとまず顔と手の同期しよう。
下のように適当なオブジェクトをシーンに置いて、NetworkObjectコンポーネントをつける。

Prefab化し、Default Network Prefabsに登録する。
これにより、Instantiateした際にもローカルだけでなくリモートでもInstantiateされる。

Network ManagerのPlayer Prefabに先程のPrefabを設定する。
これで、ゲーム再生時に自動的にマッチング開始され、プレイヤーがルームに入るとプレイヤーのPrefabも生成されるようになった。

頭と手の位置を同期する

以下のコードをPlayer Prefabにアタッチする。

public class NetworkPlayerSync : NetworkBehaviour
{
    [SerializeField] 
    private Transform head;
    [SerializeField] 
    private Transform leftHand;
    [SerializeField] 
    private Transform rightHand;
    
    private Transform _localPlayerHead;
    private Transform _localLeftHead;
    private Transform _localRightHead;
    
    // PlayerPrefabスポーン時に実行
    public override void OnNetworkSpawn()
    {
        // ローカルのプレイヤーかどうか
        if (IsOwner)
        {
            LocalPlayerSync localPlayerSync = Camera.main.transform.root.GetComponent<LocalPlayerSync>();
            _localPlayerHead = Camera.main.transform;
            _localLeftHead = localPlayerSync.leftHand;
            _localRightHead = localPlayerSync.rightHand;
        }
    }

    private void Update()
    {
        if(!IsOwner) return;
        
        // ローカルの顔の位置に合わせて、NetworkObjectの顔も動かす。
        head.position = _localPlayerHead.position;
        leftHand.position = _localLeftHead.position;
        rightHand.position = _localRightHead.position;
    }
}

これでマルチプレイでプレイヤーの頭と手の同期が可能になった。

ちなみにルーム周りの設定はデフォルトから変えていないので、ルーム入室機能などは別で作る必要があるだろうが、そこら辺はまたいつか別の記事で。

また、Metaのアバターを使用することもできる。それも別記事で書くかも?

参考文献