This document is about: PUN 1
SWITCH TO

PUN Classic (v1)、PUN 2、Boltはメンテナンスモードとなっております。Unity2022についてはPUN 2でサポートいたしますが、新機能が追加されることはありません。お客様のPUNプロジェクトおよびBoltプロジェクトが停止することはなく、将来にわたってパフォーマンス性能が落ちることはありません。 今後の新しいプロジェクトについては、Photon FusionまたはQuantumへ切り替えていただくようよろしくお願いいたします。

機能の概要

Unity 3DのためのPhotonNetworkプラグイン

PUNをインポートすると、「Wizard」ウィンドウがポップアップ表示されます。

クラウドに登録するEメールアドレスを入力するか、既存アカウントのAppIdを入力するか、または「セルフホスティング」Photonに切り替えて、サーバーのアドレスを入力してください。

これによって、プロジェクトのクラウドサービスまたは独自のPhotonサーバーの設定であるPhotonServerSettingsが作成されます。
PUNは多くのファイルで構成されていますが、非常に重要なのはPhotonNetworkです。
このクラスには、必要となるすべての関数と変数が含まれています。
カスタム要件がある場合には、ソースファイルの変更が可能です。

UnityScriptからPUNを使用するには、「PhotonNetwork」フォルダと「UtilityScripts」フォルダの両方を「Assets\Plugins\」フォルダに移動してください。

APIがどのように動作するのか、以下にいくつかの例を示します。

接続とマスターサーバー

PhotonNetworkは常に、1つのマスターサーバーと1つまたは複数のゲームサーバーを使用します。

マスターサーバーは、現在利用可能なゲームを管理し、マッチメイキングを行います。
ルームが見つかるか、または作成されると、実際のゲームプレイはゲームサーバー上でおこなわれます。

すべてのサーバーは、専用のマシンで実行されます。プレイヤーがホストするサーバはありません。
PUNが管理をおこなうため、サーバーの構成を覚える必要もありません。

C#

PhotonNetwork.ConnectUsingSettings("v1.0");

上記のコードさえあれば、接続してPhotonの機能を利用できます。
クライアントのゲームバージョンを設定し、接続するためにPhotonServerSettings(PUN Wizardによって書かれた)を使用します 。PhotonServerSettingsを変更して独自のサーバーに接続することもできます。
または、Connect()を使用してPhotonServerSettingsファイルを無視することもできます。

PhotonNetworkにはオフラインモードがあり、このモードでは、なにも書き換えることなくディベロッパーは簡単にシングルプレイヤーのゲームプレイや機能を実装できます。マッチメイキングの詳細については、PhotonNetworkオフラインモードを参照してください。

ゲームバージョンによるゲーム管理

PhotonのLoadBalancingロジックは、他のユーザーのゲームから自分のゲームを区別するためにAppIdを使用します。
プレイヤーはConnectUsingSettingsのパラメータ(上記参照)であるゲームバージョンでも区切られます。
こうすることで、ゲームの古いバージョンを壊すことなく、新しい機能を持つクライアントをリリースすることができます。

異なるPhoton Unity Networkingバージョンが互いに互換性があることを保証できないので、PUNはゲームのバージョンに自身のバージョン番号を追加します。
PUNを更新すると、古いクライアントから新しいクライアントを分離する可能性がありますが、古いクライアントが利用できなくなることはありません。

If you use PUN and non-PUN clients at the same time or if you have clients with different PUN versions,
you need to take into consideration PUN's specific AppVersion format: {gameVersion}_{PUN_version}.
So if you set the gameVersion to "1.0" in PUN and use PUN version "1.80" then the resulting AppVersion is "1.0_1.80".

If you mix PUN and non-PUN clients, be aware that PUN registers a few Unity related classes as Custom Types. That allows serialization of Unity's Vector3 but you need to check the "CustomTypes.cs" of PUN to support this in other client SDKs.

ゲームの作成と参加

次に、ルームに参加するか、またはルームを作成します。
以下のコードスニペットでは、いくつかの必要な機能を紹介します:

C#

//Join a room
PhotonNetwork.JoinRoom(roomName);

C#

//Create this room.
PhotonNetwork.CreateRoom(roomName);
// Fails if it already exists and calls: OnPhotonCreateGameFailed

C#

//Tries to join any random game:
PhotonNetwork.JoinRandomRoom();
//Fails if there are no matching games: OnPhotonRandomJoinFailed

ベストケースでは、ゲームはランダムマッチメイキングを使用します。
JoinRandomRoom() は任意のルームに参加しようとします。
これが失敗した(ルームが新たなプレイヤーを受け入れない)場合には、新しいルームを作成して他のプレイヤーがそのルームにランダムに参加するまで待ちます。

もしくは、クライアントは現在利用可能なルームのリストを取得することができます。
これはロビーへの参加によっておこなわれます。

ロビーは自動的に、クライアントにルームリストを送信して定期的に更新します(トラフィックを最小化するため)。
プレイヤーは互いを見る事も通信する事もできません(ゲームが混雑している際の問題を防ぐため)。

PhotonNetworkプラグインは接続の際、自動的にデフォルトのロビーに参加することができます。
PhotonServerSettingsファイルの「Auto-Join Lobby」のチェックボックスでオンにします。

Auto-Join Lobbyチェックボックスがオフにされていると、OnConnectedToMasterコールバックが呼ばれます。
または、OnConnectedToMasterはスキップされて、OnJoinedLobbyのみが呼ばれます。

クライアントがロビーにいる際、ルームリストの更新を取得してキャッシュします。
必要に応じて、フレームごとにGetRoomList経由でリストにアクセスすることができます。

C#

foreach (RoomInfo room in PhotonNetwork.GetRoomList())
{
    GUILayout.Label(string.Format("{0} {1}/{2}", room.name, room.playerCount, room.maxPlayers));
}

マッチメイキングの詳細は、Matchmakingとルームプロパティ を参照してください。

MonoBehaviourコールバック

PhotonNetworkは、ゲームに「接続」または「ゲームに参加」のようなステータスの変更を知らせるため、いくつかのコールバックを使用します。
Unityで通常おこなわれるよう、コールバックは任意のスクリプトで実装できます。

スクリプトがPhoton.PunBehaviourを拡張する場合、個別のコールバックをそれぞれ上書きすることができます。
その場合は、ベースの実装を呼び出す必要はありません。

C#

public override void OnJoinedRoom()
{
    Debug.Log(string.Format("OnJoinedRoom() called by PUN: {0}", PhotonNetwork.room.name));
}

PunBehaviourを拡張する必要はありません。個別で実装した場合も、すべてのコールバックは動作します。
enum PhotonNetworkingMessageにもリスト化され、説明されています。

ここでは、ゲームルーム設定の基本を説明しました。
次は、ゲーム内での実際の通信を説明します。

ゲームルームでのメッセージの送信

ルーム内では、他の接続されたプレイヤーにネットワークメッセージを送信することができます。
さらに、後から接続するプレイヤーにも送信されるバッファされたメッセージを送信できます(たとえば、プレイヤーをスポーンするなど)。

メッセージの送信は、2つの方法を用いて実行できます。
RPCを使用するか、またはPhotonViewによって監視されるスクリプト内で実装できます。

ただしネットワークには、より多くのやり取りがあります。

特定のネットワークイベントであるOnPhotonInstantiateまたはOnPhotonPlayerConnectedへのコールバックを聞いたり、たとえばPhotonNetwork.Instantiateなどのイベントをトリガーすることが可能です。

最後の一文で混乱してしまったかもしれませんが、問題ありません。以下で説明します。

PhotonView

PhotonViewは、メッセージの送信(RPCとOOnSerializePhotonView)に使用されるスクリプトコンポーネントです。
GameObjectまたはプレハブにPhotonViewを添付します。
PhotonViewはUnityのNetworkViewと非常によく似ている点に留意してください。

メッセージの送信や、オプションでPhotonViewをインスタンス化または割当てるには、常にゲームには少なくとも1つのPhotonViewが必要です。

GameObjectにPhotonViewを追加するには、GameObjectを選択して 「Components/Miscellaneous/Photon View」を使用します:

Photon Cloud: Photon View
Photon Cloud: Photon View

Transformを監視

PhotonViewのObserveプロパティにTransformを添付すると、位置、回転、スケールまたはそれらの組み合わせを
プレイヤー間で同期することができます。この機能は、プロトタイピングや規模の小さいゲームで役立ちます。
備考:監視された値を変更すると、変更された値だけでなく、すべてのObserve値が送信されます。
また、アップデートは円滑でなくなり、補間されます。

MonoBehaviourを監視

PhotonViewはMonoBehaviourを監視するよう設定できます。
この場合、スクリプトのOnPhotonSerializeViewメソッドが呼ばれます。
スクリプトがローカルのプレイヤーによって管理されているかどうかに応じて、オブジェクトのステートの書き込み、または読み込みのためにこのメソッドが呼び出されます。

以下の簡単なコードは、わずか数行のコードで、キャラクターのステート同期を追加する方法を示しています。

C#

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
   if (stream.isWriting)
   {
       //We own this player: send the others our data
       stream.SendNext((int)controllerScript._characterState);
       stream.SendNext(transform.position);
       stream.SendNext(transform.rotation);
   }
   else
   {
       //Network player, receive data
       controllerScript._characterState = (CharacterState)(int)stream.ReceiveNext();
       correctPlayerPos = (Vector3)stream.ReceiveNext();
       correctPlayerRot = (Quaternion)stream.ReceiveNext();
   }
}

オプションを監視

Observe Optionフィールドで、いつ、どのようにアップデートが送信されるかを選択することができます。
また、このフィールドはOnPhotonSerializeViewが呼び出される頻度に影響します。

Off は、PhotonViewがRPCのみに予約されている場合に役立ちます。

**Unreliable(信頼性の低い)**アップデートは、「そのまま」送信されますが、失われる可能性があります。
概念としては、次のアップデートがすぐに到着し、必要となる正しい/絶対的な値を提供するということです。
これは、位置やその他の絶対的なデータには役立ちますが、武器の交換などのトリガーには適していません。
GameObjectの位置の同期に使用する場合には、GameObjectの移動が停止(望ましくないことですが)した場合でもこれは常にアップデートを送信します。

Unreliable on Changeは各アップデートでの変更を確認します。
すべての値が前回の送信と同一の場合、1つのアップデートが信頼性の高いものとして送信され、所有者は変更が発生するまでアップデートの送信を停止します。

これは移動を停止し、しばらくの間アップデートを作成しないGameObjectに適しています。
たとえば、位置を設定後に移動しないボックスなどです。

Reliable Delta Compressedはアップデートの各値を、以前のものと比較します。
トラフィックを低くするため、変更のない値はスキップされます。受信側は、前回のアップデートの値を埋めます。

OnPhotonSerializeViewから書いたものはすべて自動的に確認され、この方法で圧縮されます。
変更がない場合、受信クライアント上でOnPhotonSerializeViewは呼ばれません。
「信頼性の高い」部分は重いため、小規模なアップデートの場合には、負荷を考慮する必要があります。

以下では、他の通信方法について説明します:RPCです。

リモートプロシージャコール

リモートプロシージャコール(RPC)を使用すると、「ネットワーク化されたGameObject」上でメソッドを呼ぶことができます。これは、ユーザー入力などでトリガーされるなど頻度の低い動作で便利です。

RPCは、同じルーム内の各プレイヤーによって同じGameObject上で実行されます。このため、シーン全体にエフェクトを簡単にトリガーできるのと同様に、GameObjectも容易に修正できます。

RPCとして呼び出されるメソッドは、PhotonViewコンポーネントを持つGameObject上に存在しなければなりません。
メソッド自体を属性: [PunRPC]でマークする必要があります。

C#

[PunRPC]
void ChatMessage(string a, string b)
{
    Debug.Log(string.Format("ChatMessage {0} {1}", a, b));
}

メソッドを呼ぶには、対象となるオブジェクトのPhotonViewにアクセスします。
対象となるメソッドを直接呼ぶかわりに、PhotonView.RPC()を呼んで、呼び出すメソッドの名前を提供します:

C#

PhotonView photonView = PhotonView.Get(this);
photonView.RPC("ChatMessage", PhotonTargets.All, "jup", "and jup!");

パラメータのリストを送信できますが、このリストはRPCメソッドの定義と一致する必要があります。

以上が基本的な設定です。詳細はリモートプロシージャコールを参照してください。

Back to top