以前、MLAPIを使ってマルチプレイを作りまして、Netcode for GameObjects(以下、NGOと呼ぶ)を実装してみようと思い、色々調べたら、まさかNGOがMLAPIの次のバージョンみたいなものだと知って驚きました。
今回はそのNGOを使ったマルチプレイの実装方法を紹介していきます。
事前準備
- UnityHub
- UnityEditor(2020.3(LTS), 2021.3(LTS), 2022.2のものしか動きません)
UnityEditorのバージョンだけは特に気にしてください。上記のもの以外で実装することはできません。今回は2022.3.1f1を使います。
私はこれに気づかずに丸一日苦戦してました
実装方法
プロジェクトの作成
上記のバージョンに合うバージョンで、プロジェクトを作ってください。2Dでも3Dでも構いませんが、私は2Dで作りました。
パッケージのインストール
Windows > Package Managerを開き、「Packages」の項目をUnity Registryにします。
そしたらその左隣にある「+」を押し、Add package by nameを押してから、以下の名前を記入(またはコピー&ペースト)してください。
com.unity.netcode.gameobjects
参加用のボタンを作成する
ホストとクライアントで参加できるようにしましょう。
参加できるようにするスクリプトを作成する
アセット内にNetworkUIを作り、そのスクリプト内で、下記のコードを入力してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NetworkUI : MonoBehaviour
{
public void StartHost()
{
Unity.Netcode.NetworkManager.Singleton.StartHost();
}
public void StartClient()
{
Unity.Netcode.NetworkManager.Singleton.StartClient();
}
}
ホストの参加とクライアントの参加の処理をしています。
それぞれボタンを押したときに処理するようにします。
これを書きましたら、ヒエラルキーの中にあるEventSystemに、先程作ったスクリプトを入れます。
ホストとクライアントのボタンを作成する
ヒエラルキーに、Button - TextMeshProを2つ追加します。
ボタンの中にある**On Click()**の項目に、先程入れたNetworkUI.csの中の処理を入れます。
こうなっていればOKです。
プレイヤーのプレハブを作成する
プレイヤーのモデルとなるものをヒエラルキー内に作ります。今回私は2Dで制作をしているので、2Dの円スプライトを使います。名前もちゃんとわかりやすいようにPlayerにしておきましょう。
生成できたら、その中に以下の項目を追加します。
- Network Object
- Network Transform
- Network Rigidbody 2D(Rigidbody 2Dもここで生成される)
- Circle Collider(四角でもカプセルでもなんでもいい)
-
Player Controller(リンク先で説明します)
中身の設定につきましては、特に問題がなければそのままで大丈夫です。
物理挙動について色々設定したい場合は設定しましょう。
プレイヤーの移動部分のスクリプトを作成する
アセットの中にPlayer Controllerを作成します。
スクリプトの中身を開いたあと、必ず継承先を下記のものに変更してください。
Unity.Netcode.NetworkBehaviour
そしたらあとはプレイヤーの移動を処理するプログラムを書くだけです。
例として上げておきます。
if (this.IsOwner)
{
Vector2 velocity = new Vector2();
if (Input.GetKey(KeyCode.W))
{
velocity.y = 1.0f;
}
else if (Input.GetKey(KeyCode.S))
{
velocity.y = -1.0f;
}
if (Input.GetKey(KeyCode.A))
{
velocity.x = -1.0f;
}
else if (Input.GetKey(KeyCode.D))
{
velocity.x = 1.0f;
}
velocity.Normalize();
SetMoveInputServerRpc(velocity);
}
if(this.IsServer)
{
_rigidbody2D.velocity = new Vector2(_velocity.x * _moveForce, _velocity.y * _moveForce);
}
[Unity.Netcode.ServerRpc]
private void SetMoveInputServerRpc(Vector2 velocity)
{
_velocity = velocity;
}
ここで必ずやってほしい処理を上げていきます。
- 自分の持ちキャラの場合、入力処理を行う。
- 動いた分をサーバへ渡す。
- サーバ側で移動処理を行う。
それぞれ説明します。
自分の持ちキャラの場合、入力処理を行う。
if (this.IsOwner)
これは、自分の持ちキャラの場合という条件文になっています。
これがないと全キャラ操作できるようになってしまいます。必ずこの条件分を使いましょう。
注意してほしいのが、後に説明する動いた分をサーバーへ渡す処理でも条件文を使うので、
if (!(this.IsOwner))
{
return;
}
これは控えたほうがいいかもしれません。
動いた分をサーバへ渡す。
[Unity.Netcode.ServerRpc]
private void SetMoveInputServerRpc(Vector2 velocity)
{
_velocity = velocity;
}
これは、動いたものををサーバーへ渡す処理をしています。
関数の上に、
[Unity.Netcode.ServerRpc]
これをつけることで、サーバへ渡す処理ができるようになるそうです。すごいですね。
サーバ側で移動処理を行う。
if(this.IsServer)
これは、自分がサーバの場合という条件文になっています。
主に物理挙動の処理を行うのに使います。
プレハブ化させる
ここまで作ったプレイヤーのオブジェクトをアセットの中へ移動させると、プレハブ化することができます。
プレハブ化させたら、ヒエラルキーに残っているプレイヤーオブジェクトは必要ないので削除します。
シーン内にNetworkManagerを作成する
ヒエラルキーに空のオブジェクトを作成し、そのオブジェクトの名前をNetworkManagerにしてください。
そのオブジェクトの中に、Network Managerという名前のコンポーネントを追加してください。
そしたらこのような画面になるので、Select transport... のところを選択し、その中にあるUnity Transportを選択してください。
Player Prefabに、アセットの中にあるプレイヤーのプレハブを、
Network Transportに、ヒエラルキー内にあるNetworkManagerを入れます。
こうなってたらOKです。
ビルドの準備を行い、実際にビルドをする
File > Build Settings... > Player Settingsこの順で開いていき、Resolution and Presentationの中にある、Default Screenを1280 * 720にします。もっと小さくでも良いです。
そしたらビルドを行いましょう。
実際に動かしてみる
ビルドしたフォルダの中にある実行ファイルを2つ開きます。
一つのウィンドウではホストで参加し、もう一つのウィンドウではクライアントで参加してください。
クライアント側で動かしているものが、実際にサーバ側で動いていたら成功です。お疲れ様でした。
なにか不具合等あれば連絡してください。