【Unity】Netcode for GameObject (NGO)でプレイヤーの位置や向きを同期するプログラムまとめ

2022年8月22日

どうも、こんにちは。
ただの大学生です。

今回は、Netcodeでプレイヤーの位置や向きなどを同期する方法を3つほどご紹介したいと思います!

私自身がNetcodeでマルチプレイのゲームを開発していた時に、Netcodeの日本語記事がほとんどなくて困っていたので、役に立てたら幸いです!


Network Transformを使う

まずは標準的なものから行きましょう。

Netcodeをインストールした際についてくるスクリプトの中に「Network Transform」というものが用意されており、これを使うことでプレイヤーなどネットワークで同期したいオブジェクトの位置や向きを自動で同期してくれます。

ただ、このスクリプトの厄介なところが、移動がサーバーサイドでしか行われないため、クライアント側ではずれが生じてしまいます。

詳しくは是非こちらの動画を見ていただければいいのですが、この「Network Transform」では、

  1. クライアントがキーを押す
  2. サーバーにキーが押されたことを伝える
  3. サーバー側で動かす
  4. クライアントに動かしたことを伝える
  5. クライアント側でプレイヤーが動く

といったような処理になっているので、キーを押してからラグが感じられます。

これがFPSなどの精度を求められるゲームの場合は困る時があります。

そういう時は以降2つのやり方を使ってみてください。


Client Network Transformを使う

次にClient Network Transformというスクリプトを使う方法があります。

これは、少し前まではNetcodeの拡張パッケージ(?)として用意されていたのですが、なぜかなくなってしまいました。

今ではこちらのGitHubページからダウンロードできますので、直接インストールでも、コードをコピペでもよいので自身のUnityプロジェクトに持っていき、同期したいオブジェクトに張り付けましょう。

GitHubリンク:https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs

私自身もこのスクリプトについて詳しくはわからないのですが、(わかろうとするとNetcodeのコードを理解しないといけない?)先ほど言ったサーバー側で動きが同期されるのではなく、クライアント側で動かして、その動かした結果をサーバーに伝えるという形になっています。

なので、ラグが感じにくく、プレイヤーにとってプレイ感が良くなります。

ただ、もちろんこちらにもデメリットはあり、クライアント側で処理されるということは、チートが行われる可能性が増えたりします。

そこは一長一短ですね。


自分でコードを作る

最後に、自分自身でコードを作るという手があります。

今回は、プレイヤーのY軸の向きと位置を同期したかったので、Netcodeに用意されているNetwork Variable(ネットワーク上で同期してくれる変数)として、Vector3型のposとint型のrotを用意しました。

以下が作ったプログラムです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class ClientNetworkTransform : NetworkBehaviour
{
    private NetworkVariable<Vector3> pos = new(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
    private NetworkVariable<int> rot = new(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
    // Update is called once per frame
    void Update()
    {
        if(IsOwner)
        {
            //反映
            pos.Value = transform.position;
            rot.Value = (int)transform.rotation.eulerAngles.y;
        }
        else
        {
            //位置と向きを設定
            transform.position = pos.Value;
            transform.rotation = Quaternion.Euler(0f, rot.Value, 0f);
        }
    }
}

Network Variableというのは、先ほども書いた通りネットワークで同期してくれる変数で、基本的にはサーバー側でしかその値を変えることはできません。

ただ、コンストラクタ(new()の括弧の中に入れると設定が変えられる)を使って、この変数のOwner(クライアント)で変えられるように変更して、このプログラムを実装しています。

またネットワーク上で大きさなどを同期したい場合は、追記すると動かすことができるので、自由にカスタマイズできるのも自分で書く利点です。


最後に

というわけで今回はここまでとします。

Netcodeに関する記事ほとんどなくて、触ったことのある人ならどのように実装すればいいのかわからなくて困ったこと、あるんじゃないんでしょうか…?

Netcodeの仕組みやプログラムについて調べると、(誰も使っていないので)公式のReferenceしかないんですよね…

質問などあれば是非Twitterの方にブログかご連絡ください!

私自身も完全に理解しているわけではないですが、出来るだけがんばって返します…!

また他にもNetcodeの記事を書いていきたいと思うので、よければまた見てください!

長くなってしまいましたが、

最後まで読んでいただきありがとうございました!

このブログでは、他にも初心者向けのプログラミングの記事やゲーム紹介の記事を書いていますので、良ければ是非読んでみて下さい!

おすすめ記事: