はじめに
みなさんどうも、はじめましての方ははじめまして、そうでない方もはじめまして、19のNと申します。今回は、Unityで簡単に(?)オンラインゲームが作れちゃうPhotonの機能をご紹介します。公式のドキュメントが読みづらかったり、英語だったり、するので覚書も含めています。それではさっそくいってみましょう。
Photonの概要
Photonって…?
PhotonとはUnityで簡単にオンラインゲームが作れちゃうミドルウェアです。UnityAssetsStoreからPUN2と検索して出てきたものをインポートすればすぐに使うことができます。ルームの作成や、プレイヤー間でのオブジェクトの同期など、様々なことをやってくれます。
Photonを使うには???
Step1
- 公式サイトでアカウントを登録し、ログイン。
- 右上の Dashbord をクリックして YourApplications に飛び、CREATE A NEW APP で新しいアプリを登録。
- アプリのApp IDというものをメモ。(コピペ)
Step2
- Unityを開き、AssetsStoreからPUN2をインポート。
- 先ほどメモしておいたApp IDを登録。
- PhotonServerSettingsからDevRegionをjpにする。
これでPhotonが使えるようになりました。もっと詳しい手順は公式ドキュメントを読んでください。
Photonの基礎知識
ルームとロビー
Photonにはルームとロビーという二つの状態があります。ロビーとはマッチングの待機場所というイメージで、ルームは実際にゲームをするところ、という風に理解していれば大丈夫だと思います。
マスタークライアント
Photonではマスタークライアントというホストプレイヤーのようなものがあります。全員揃ったらゲームをスタートする、などのマスタークライアント特有の処理をさせることができます。複数プレイヤーいるなかで、特別なプレイヤーと思ってもらえれば大丈夫です。
PhotonView
PhotonにはPhotonView
という便利なコンポーネントがあります。これをつけてるオブジェクトは他プレイヤーに同期されます。座標や、アニメーションなど、様々なものを同期することができます。
MonoBehaviourPunCallbacks
同期するオブジェクトにスクリプトをつけるとき、MonoBehaviourPunCallbacks
というクラスを継承することになります。これにはルームに入ったときの処理、他プレイヤーがルームに入ってきたときの処理、など様々なコールバック関数が入っています。これをオーバーライドすることで、そのときどきに応じたコールバック関数に機能をつけたすことができます。
実践Photon
ロビーに入る→ルームを作成orすでにあるルームに入る
サーバーに接続
テキトーなスクリプトにMonoBehaviourPunCallbacks
を継承して以下のConnect
関数でサーバーに接続できる。以下、継承部分などは省略する。
using Photon.Pun;
using Photon.Realtime;
public class NetworkManager : MonoBehaviourPunCallbacks{
public void Connect()
{
if (!PhotonNetwork.IsConnected)
{
PhotonNetwork.ConnectUsingSettings();
}
}
}
ロビーに入る
他の記事ではいきなりルームに入るような仕様のものが多いが、本記事ではロビーに入る→ルームを作成して入る or 他の人が作ったルームに入る のような流れで実装する。
MonoBehaviourPunCallbacks
の中にあるOnConnectedToMaster()
というサーバーに接続したときに呼ばれるコールバック関数でPhotonNetwork.JoinLobby
を呼び出す。これによって、ロビーに接続した状態になる。(他のプレイヤーが作ったルームなどが見える状態になる。)
public override void OnConnectedToMaster()
{
PhotonNetwork.JoinLobby(customLobby);
}
ルームを作る
以下のCreateRoom()
関数を作成して、適当なbuttonなどにつけたらできる。ルームごとのプロパティを設定することができて、以下ではルームの名前とメッセージを設定している。他にもいろんなものをつけられる。nickname
は適当なinputfieldとかから受け取ればよい。
public void CreateRoom()
{
string nickname = inputfield.text;
Photon.LocalPlayer.NickName=nickname;
PhotonNetwork.CreateRoom(
$"{nickname}'s room",
new RoomOptions()
{
MaxPlayers = MAX_PLAYER_NUM,
CustomRoomProperties = new ExitGames.Client.Photon.Hashtable()
{
{ "DisplayName", $"{nickname}'s room" },
{ "Message", "Anyone can join !" }
},
CustomRoomPropertiesForLobby = new[]
{
"DisplayName",
"Message"
},
IsOpen = true,
IsVisible = true,
}
);
}
すでにあるルームの一覧を取得
OnRoomListUpdate(List<RoomInfo> roomList)
というルームが新しく作られたときに呼ばれる便利なコールバック関数がある。roomList
にルームの一覧が入っている。これを使って、以下ではroomListView
という別のクラスで取得したルームをUIに反映させる処理をしている。ここではPhotonの機能に限ったことを紹介するので、その辺は省く。
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
roomListView.OnRoomListUpdate(roomList);
}
すでにあるルームに入る
以下のJoinRoom
関数を適当なbuttonなどにつければよい。ここではルームに入った後、Game
シーンに遷移するようにしている。
private void JoinRoom(string roomName)
{
PhotonNetwork.JoinRoom(roomName);
PhotonNetwork.IsMessageQueueRunning = false;
PhotonNetwork.LoadLevel("Game");
}
プレイヤー操作周りの実装
同期するオブジェクトのインスタンス化
プロジェクト直下にResources
という名前のフォルダを作ってそこにPhotonView
コンポーネントを付けたPrefabを入れる。以下ではプレイヤーオブジェクトをインスタンス化している。
player = PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f, 0f, 0f), Quaternion.identity, 0);
マスタークライアントのみで処理
if (PhotonNetwork.IsMasterClient)
{
// 実際の処理
}
自機のみで処理
if (photonView.IsMine){
// 実際の処理
}
自機の変更を同期
PunRPCという機能を使えば自機のクライアントでの変更を他プレイヤーに同期させることができる。以下のように[PunRPC]
をつけた関数をphotonView.RPC
で呼び出せばできる。第二引数をRpcTarget.AllViaServer
にすると、サーバーで一括処理してから反映という風にすることができる。他にも色々な設定があるので、詳しくは公式ドキュメントなどを参照。
photonView.RPC(nameof(playerUpdate), RpcTarget.All, args);
[PunRPC]
playerUpdate(var args)
{
// 実際の処理
}
プレイヤーに様々なプロパティを設定
CustomProperties
という機能を使う。
- プロパティを設定(ここでは"State"というプロパティを設定)
var hashtable = new ExitGames.Client.Photon.Hashtable();
hashtable["State"] = state;
PhotonNetwork.LocalPlayer.SetCustomProperties(hashtable);
- 他プレイヤーのプロパティを取得(ここでは
int
型の"State"というプロパティを取得)
foreach (var p in PhotonNetwork.PlayerList)
{
int pstate = (int)p.CustomProperties["State"];
}
最後に
Photonで作ったオンラインゲームを近日PlayStoreで公開予定…???!!!刮目せよ!!!!
明日はプロエロゲーマー、エロゲで金を稼ぐ美少女、あの有名なryohaさん?!の記事です。おたのしみに。