server | v4 switch to v3  

Photonプラグイン よくある質問

Photonプラグインは、Enterprise CloudまたはセルフホスティングされたPhoton Server v4でのみ利用可能です。

Contents

設定

Photon Serverのカスタムプラグインの設定方法は?

app.configにPlugin XMLノードを追加する必要があります。

必要最低限の要素は以下のとおりです:

Webhookプラグインの設定例:

詳細は、プラグインマニュアルの「設定」セクションを参照してください。

Back To Top

Photonは複数のプラグインをサポートしていますか?

アプリケーションには1度に1つのプラグインアセンブリ(DLL)やプラグインファクトリしか設定することができません。 このDLLでは、いくつでもプラグインを持つことができます。 ルーム作成時に読み込まれ、インスタンス化されるプラグインは1つです。 プラグインのルームとインスタンスの間には1対1の関係があります。つまり、各ルーム​​にはプラグインの独自のインスタンスがあります。

以下の設定は許可されていません:

Back To Top

ルーム作成時に、どのプラグインを使用するか選択する方法は?

私たちのプラグインモデルは、ファクトリのパターンを使用しています。 プラグインは、必要に応じて名前からインスタンス化されます。

クライアントはroomOptions.Pluginsを使用して、プラグインのセットアップを要求しルームを作成します。 roomOptions.Pluginsstring[]型で、最初の文字列(roomOptions.Plugins[0])はファクトリに渡されるプラグイン名にする必要があります。

例:
roomOptions.Plugins = new string[] { "NameOfYourPlugin" };
または roomOptions.Plugins = new string[] { "NameOfOtherPlugin" };

クライアントが何も送信しない場合、サーバーはデフォルト(何も設定されていない場合)、または設定されている場合はプラグインファクトリが作成時に返すものを使用します。

ファクトリでは以下のように名前を使用して、対応するプラグインを読み込みます:

PluginFactory.Createで返されたプラグインの名前がクライアントによってリクエストされたものと一致しない場合は、 プラグインはアンロードされ、クライアントの作成または参加オペレーションは失敗してPluginMismatch (32757)エラーとなります。

Back To Top

実行時にディスクからファイルを読み込みたいです。プラグインは、ファイルシステムへのアクセス権を持っていますか?外部のサーバーからファイルをダウンロードする必要がありますか?

プラグインに必要不可欠なものと一緒に、追加のファイルをアップロードすることができます。 ファイルへのパスは、その後typeof(yourplugin).Assembly.Locationを使用して取得することができます。

Back To Top

依存モジュール(DLL)は自動的にメインプラグインDLLと共に読み込まれますか? なぜSystem.TypeLoadExceptionを取得してしまうのでしょう?

外部モジュールの使用は、プラグインソリューションのDLLやプロジェクトを参照することで動作します。 参照されるすべての依存関係のモジュールをプラグインDLLと同じディレクトリにデプロイし、それらが読み込まれてリンクされることを確認してください。

Back To Top

コールバック

プレイヤーがルームに入ろうとすると、どのメソッドが呼ばれますか?

この質問に答えるためには、作成、参加、再参加によりプレイヤーがルームに入る際のシナリオが4つある点を理解する必要があります。

一般的にJoinRoomCreateRoomオペレーションの構造は非常に似ています。 異なるJoinModeの値を持つ1つの論理的なJoinオペレーションと考えると良いかもしれません。

  1. Create: OpCreateRoom:ルームがすでに存在している場合、エラーが返されます。
  2. Join: OpJoinRoom(JoinMode.Default または設定されていない)、OpJoinRandomRoom: ルームが存在しない場合、エラーが返されます。
  3. CreateIfNotExists: OpJoinRoom (JoinMode.CreateIfNotExist): ルームが存在しない場合、ルームを作成します。
  4. RejoinOnly: OpJoinRoom (JoinMode.RejoinOnly): アクターがルームにすでに存在しない場合、エラーが発生します。

ルームがメモリに有る場合、2)から4)はBeforeJoinをトリガーし、{ICallInfo}.Continue()を呼ぶことを仮定して、OnJoinが呼び出されます。

プラグインが設定されアクターがルームに追加される直前、ルーム作成の直後にOnCreateGameが呼び出されます。 これは1)、3)および4)によってトリガーすることができます。 後者は、状態の保存と読み込みが正常に処理された場合にのみ発生します。 これは、プレイヤーがサーバーのメモリから削除されたルームへの再参加を要求し​​たときに発生します。 Photonは、それでも作成を行いプラグインを設定します。 プラグインは、データベースまたは外部サービスからシリアル化された状態を取得し、SetSerializedGameStateを呼びます。 状態には、非アクティブ状態のアクターリストが含まれます。再入室によって、アクターは再び有効になります。

Back To Top

プラグインコールバックでアクター番号を取得する方法は?

プラグインhookでActorNrを取得する方法は以下のとおりです:

1. OnCreateGame, Info.IsJoin == False:

ゲームの最初のアクターで、ゲームを作成したアクターです。アクター番号は常に1に設定されます。

Back To Top

2. OnCreateGame, Info.IsJoin == True:

A. Info.Continue()の前;

ゲームの状態の読み込みによって、ルームが「再作成」される場合に備えて、非アクティブユーザーのリストから、UserIdでActorNrを取得してください。 読み込んだルームの状態からUserIdと比較してActorListを確認し、ゲーム状態でアクター番号を検索する必要があります。 (UserIdが利用できない場合には再参加は失敗し、CheckUserOnJoinとアクターごとのUserIdによってルームを作成しなければなりません) 

// load State from webservice or database or re-construct it
if (this.PluginHost.SetGameState(state))
{
    int actorNr = 0;
    foreach (var actor in PluginHost.GameActorsInactive)
    {
        if (actor.UserId == info.UserId)
        {
            actorNr = actor.ActorNr;
            break;
        }
     }
     if (actorNr == 0)
     {
         if (!asyncJoin)
         {
             // error, join will fail with
             // ErrorCode.JoinFailedWithRejoinerNotFound = 32748, // 0x7FFF - 19,
         }
         else
         {
             actorNr = PluginHost.GetSerializableGameState().ActorCounter + 1;
         }
   }
}

その他の場合、「正しい」ActorNrをJoinRoomオペレーションでクライアントから送信すると、info.Request.ActorNrから取得できます。

Back To Top

B. Info.Continue()の後;

アクティブなアクターのリストからUserIdでctorNrを取得します。

int actorNr;
foreach (var actor in PluginHost.GameActorsActive)
{
    if (actor.UserId == info.UserId)
    {
        actorNr = actor.ActorNr;
        break;
    }
}

Back To Top

3. BeforeJoin

A. Info.Continue()の前;
int actorNr = 0;
switch (info.Request.JoinMode)
{
    case JoinModeConstants.JoinOnly:
    case JoinModeConstants.CreateIfNotExists:
        actorNr = PluginHost.GetSerializableGameState().ActorCounter + 1;
        break;
    case JoinModeConstants.RejoinOnly:
        foreach (var actor in PluginHost.GameActorsInactive)
        {
            if (actor.UserId == info.UserId)
            {
                actorNr = actor.ActorNr;
                break;
             }
         }
         if (actorNr == 0)
         {
             // error, join will fail with
             // ErrorCode.JoinFailedWithRejoinerNotFound = 32748, // 0x7FFF - 19,
          }
          break;
      case JoinModeConstants.RejoinOrJoin:
          foreach (var actor in PluginHost.GameActorsInactive)
          {
              if (actor.UserId == info.UserId)
              {
                  actorNr = actor.ActorNr;
                  break;
              }
           }
           if (actorNr == 0)
           {
               actorNr = PluginHost.GetSerializableGameState().ActorCounter + 1;
           }
           break;
}

その他の場合、「正しい」ActorNrをJoinRoomオペレーションでクライアントから送信すると、info.Request.ActorNrから取得できます。

Back To Top

B. Info.Continue()の後;

アクティブなアクターのリストから、UserIdでActorNrを取得します。

int actorNr;
foreach (var actor in this.PluginHost.GameActorsActive)
{
    if (actor.UserId == info.UserId)
    {
         actorNr = actor.ActorNr;
         break;
    }
}

Back To Top

4. OnJoin, OnRaiseEvent, BeforeSetProperties, OnSetProperties, OnLeave:

利用可能なinfo.ActorNrを使用してください。

Back To Top

5. BeforeCloseGame, OnCloseGame:

hookがクライアントオペレーションではなくサーバーによってトリガーされているため、ActorNrを取得する方法はありません。

Back To Top

サーバーからルームを作成できますか?

いいえ、それは不可能です。

Back To Top

サーバーからルームを削除できますか?

現時点では、不可能です。

Back To Top

プラグインイベントで利用可能なデータを把握する、最適な方法は?

一般的に、イベントのICallInfo コールバックパラメータは必要なものを公開する必要があります。 多くの場合、実際のオペレーションは{ICallInfo}.OperationRequest (またはRequest)プロパティによって取得可能なパラメータをリクエストします。

Back To Top

UseStrictModeは何を行いますか?

プラグインの概念は、受信リクエストを処理する前または後に、「通常」のPhotonフローにフックすることです。

当初、弊社はユーザーが何かを呼び出すことを強制しませんでした。これは、本質的に受信したリクエストのデフォルト処理をキャンセルすることと同じでした。 これにより、ディベロッパーはデフォルトのコールバックロジックを使用せずに、必要なものを一から実装しなければなりません。結果的に複数の予期せぬ問題が発生しました。ディベロッパーは常にキャンセルをしたいわけではありません。 そこでstrictモードを導入し、ディベロッパーが決定できるようにしました。 現在はContinueFailまたは Cancelのいずれかを1回のみ呼びます。また、処理を遅延させるDeferメソッドもあります。

Back To Top

PluginBaseのコールバックメソッドをオーバーライドするときbase.XXX()を呼ぶ必要はありますか?

PluginBase内のすべてのコールバックメソッドには、最後に行われるContinue()への呼び出しが含まれています。 概念としては、PluginBaseから継承することで、自分が興味のあるメソッドのみオーバーライドすることができます。 base.XXX() の前か後にコードの追加が必要な場合や、 デフォルトの動作の完全な変更が必要な場合があります。 前者の場合は、ICallInfo処理メソッドに呼び出しを追加すべきではありません。 後者の場合は、base.XXX()を呼び出さず、一からメソッドの独自の実装を行い、利用可能なICallInfo処理メソッドの1つに呼び出しを追加します。 唯一の例外は、PluginBase.OnLeaveです。 このメソッドは、現在のMasterClientが退出する場合にMasterClientの変更を処理します。

Back To Top

イベント

HttpForwardプロパティとWebFlagsクラスは、何を行ないますか?

これらはWebHookに関連する機能です。 WebFlagsはWebHook v1.2のプラグインで導入されています。WebFlagの詳細についてはこのページを参照してください。 HttpForwardは、対応するwebflagの値を示すプロパティです。

本来はWebHookとWebRPCのために作られていますが、プラグインでそれらを使用することも可能です。

Back To Top

プラグインからイベントを送信する方法は?

これにはPluginHost.BroadcastEventを使用する必要があります。 クライアントからイベントを送信するのと同じ様に動作しますが、サーバーを表すために送信元アクター番号を0に設定することができるのが主な違いです。

this.PluginHost.BroadcastEvent(
            recieverActors: new int[] { targetPlayerNr },
            senderActor: 0,
            data: new Dictionary<byte, object>() { { 1, data } },
            evCode: (byte)code,
            cacheOp: 0,
            sendParameters: new SendParameters() { Unreliable = false });

詳細は「プラグインからのイベントの送信」セクションを参照してください。

Back To Top

OnRaiseEventから行なった場合とは異なりOnJoinコールバック内で呼ばれた場合にPluginHost.BroadcastEventがクライアントへのイベントの送信に成功しないのはなぜですか?

OnRaiseEvent ではクライアントが既に参加しているので、イベントを受信できます。 OnJoinでは、{ICallInfo}.Continue()を使用してリクエストが処理されない限り、クライアントは完全に参加されません。

つまり、{ICallInfo}.Continue()の後にPluginHost.BroadcastEventが呼ばれた場合、イベントはターゲットクライアントによって受信される必要があります。

プラグインhookは、以下のように動作します:{ICallInfo}.Continue()への呼び出しで、Photonの通常の処理をトリガーします。 この場合、完全に参加した後にイベントを送信したほうが理にかなっています。

Back To Top

プラグインから送信されたイベントデータをクライアントが受信できないのはなぜですか?

これは既知の問題です。クライアントは、イベントがあらかじめ定義された特定の構造と既知のキーコードを有することを想定しています。 イベントデータは245、アクター番号は254です。 これを修正するには、プラグインからイベントデータを送信する方法で軽微な変更を行います。(Dictionary<byte,object>)eventDataの代わりにnew Dictionary<byte,object>(){{245,eventData},{254,senderActorNr}}を送信します。

Back To Top

プラグインはカスタムオペレーションに対応していますか?

いいえ、現状プラグインはカスタムオペレーションをサポートしていません。 Photonプラグインは、一連のネイティブオペレーション(「Create」、「Join」、「SetProperties」、「RaiseEvent」および 「Leave」)のみに対応するコールバックを提供します。 カスタムオペレーション(セルフホスティングされたPhoton Serverで追加済み)を受信することはできません。 また、プラグインSDKを使用して新しいものを拡張することはできません。

しかし、2方向のイベントをやりとりすることで、同じ結果を得ることができます。

  • クライアントからプラグインにLoadBalancinglient.OpRaiseEventを呼び出す。
  • プラグインからクライアントにPluginHost.BroadcastEventを呼び出す。

Back To Top

ゲームの状態

「アクティブ」ユーザーと「非アクティブ」ユーザーはどのように区別されますか?

プレイヤーが切断すると、Photonは通常クリーンアップを行いアクターが削除されますが、 ルームを作成するときにクライアント上で CreateOptionsPlayerTTL を定義できます。 正の数である場合、Photonはクリーンアップを開始する前にその時間(ミリ秒単位で定義)待ちます。 その間、アクターは非アクティブとみなされ、ゲームに再度参加することができます。それが正常に行われた場合、プレイヤーは再びアクティブになります。

接続の不良によりプレイヤーが切断されても短い時間内(数分)であれば戻ることのできるようなRTSゲームなどの場合に、ゲームの状態を保存してプレイヤーを継続させるために、この機能を使用することができます。

PluginHost.GameActorsActiveには、ルーム内(参加済み)のすべてのアクターが含まれていて、PluginHost.GameActorsInActiveにはルームを退出した(放棄せずに)すべてのアクターが含まれています。

Back To Top

プラグインで、アクターをルームから退出させることはできますか?その方法は?

はい、可能です。プラグインクラスからは、PluginHost.RemoveActor(int actorNr, string reasonDetails)を呼び出す必要があります。3つのパラメータ:PluginHost.RemoveActor(int actorNr, byte reason, string reasonDetails)を受け取るメソッド負荷を呼び出すことで、理由を設定できます。

Back To Top

ルームの状態を保持するには?

ルームの状態を保存するには:

  1. PluginHost.GetGameStateを呼び、SerializableGamestateを取得します。
  2. 状態を非シリアル化します(たとえば、JSON)。
  3. データストアに状態を保存します。

ルームの状態を読み込むには:

  1. データストアから状態を取得します
  2. 状態を非シリアル化します。
  3. PluginHost.SetGameStateを呼びます。

注: {ICallInfo}.Continue()を呼ぶ前には、OnCreateGameでPluginHost.SetGameStateを呼ぶことのみが許可されています。

Back To Top

SerializableGameState内のいくつかのカスタムルームプロパティを見つけることができません。ロビーのプロパティのみなのはなぜですか?

シリアル化が可能なゲーム状態では、設計によりすべてのカスタムプロパティへのアクセスが提供されるわけではありません。 ロビーで共有したもののみが公開され、それは「閲覧」目的のみです。 組み合わせたすべてのプロパティは、バイナリ配列に含まれています。 これによりJSONにシリアライズ化し、デシリアライズ化で戻した時に型情報を失わずにすみます。 この機能は、主に保存/読み込みのシナリオ向けに設計されています。 将来的にこの挙動は変更される可能性があります。

Back To Top

プラグインからルームプロパティ(MaxPlayers, IsVisible, IsOpen など)にアクセスする方法は?

すべてのルームプロパティは、Hashtable型であるPluginBase.PluginHost.GamePropertiesからアクセス可能です。 これらのプロパティには、「ネイティブ」または「既知」のものが含まれます。 それらには、LoadBalancingクライアントSDK、またはそれぞれのAPIリファレンスページによって、LoadBalancing.GamePropertyKeyから取得可能な値を参照するbyteキーがあります。

int(例:MaxPlayers = (byte)255)からbyteにキーをキャストしてください。 将来的には、これらの値を取得するためのより良い方法を提供する予定です。

カスタムのルームプロパティはPluginHost.GameProperties にも含まれます。 ディベロッパーは、責任を持ってこれらのキー/値の処理をおこなってください。

一方、ロビーから見えるカスタムプロパティのみが、Dictionary<string, object>である PluginBase.PluginHost.CustomGamePropertiesに格納されます。

以下のように、プラグインからルームとアクターのプロパティにアクセス(読み込みおよび書き込み)することができます:

読み込みの例:

書き込みの例:

Back To Top

スレッディング

Net Pluginコンポーネントでの、スレッディングの要件について詳細を記載します。

単独のPhoton Serverでいくつのスレッドが実行されていますか?

スレッドの利用は以下のように分けられます:

  1. ネイティブ - 9個のスレッド
  2. 管理 - .Netデフォルト設定を使用する.Net ThreadPoolにもとづく。

この設定には非常に厳密にテストをおこなってきましたので、広範な負荷プロファイルに対して問題なく動作します。

管理スレッドの使用は、状況によって異なります(.Net Windows Performanceカウンターに記載されたとおりです):

a) 1個~12個まで:通常のPhoton Cloud Realtime負荷に対応 b) 35個以上:プラグイン間の通信(ロッキング)をともなうプラグインを実行するカスタマークラウドが例で、より高いコンテンションの原因となります(弊社のコードとは対照的です)。

備考:必要に応じて.Net ThreadPool設定は調整できます。 これまでデフォルトの設定で適切な成果が得られていますが、それぞれの状況に応じて調整が必要かもしれません。

Back To Top

Photonのホストはフリースレッドですか?すべてのスレッドがいつでもすべてのルームにアクセスできますか?

メッセージパッシングアーキテクチャを使用しています:プラグインは一度に1つのスレッドにのみ呼び出されます。 しかし、スレッドプールを使用するので各呼び出しのスレッドは同じではないかもしれません。

Back To Top

Aプラグインの書き込み時に、スレッドでの安全性の問題点はありますか?

一般的に、プラグインへのすべてのコールがシリアル化されていると想定するのが安全です(実質的に1つのスレッド上/物理的に同じスレッド上である必要はありません)。

Back To Top

Enterprise Cloud

Enterprise Cloudのランタイム環境に関連した質問を以下に記載します。

プラグインの設定方法は?

Photon Enterprise Cloudには: Photonダッシュボードからアプリケーションの管理ページに移動して、新しいプラグインを追加する必要があります。 そこから、ページ下部の「新しいプラグインを作成」ボタンをクリックしてください。 これで、キー/値のエントリを追加することでプラグインを設定することができます。 AssemblyNameVersionPath、およびTypeは必須です。

Back To Top

Photonプラグインを作成する際のパイプライン処理は何ですか?

Photonプラグイン作成時のパイプライン処理は簡単です:

  1. 必要なSDKとサーバーバイナリをダウンロード。
  2. プラグインのアセンブリをコーディングおよび構築。 
  3. デプロイしてテストします。
  4. アップロードします。 
  5. 設定します。 

Photonプラグインの環境設定は以下のとおりです:

  • 開発: ローカルマシン
  • テスト: ローカルネットワーク
  • ステージング: クラウドの個別のAppID
  • 本番: クラウドの本番のAppID

Back To Top

プラグインのアップロードは自動化されていますか?

Enterprise Cloudをご利用中のお客様にはPowerShellスクリプトが提供され、GMOクラウド Privateクラウドの管理に役立ちます。 詳細はプラグインアップロードオンラインガイド で確認してください。

Back To Top

プラグインのパフォーマンスを監視するには?

ダッシュボードで利用できる複数のカウンターは、トラッキングされています。 また、カスタムのカウンターを追加したり、カウンター用に外部ツールを統合することも可能です(例:New Relic)。 これらのサービスを使用する場合には、弊社とのコンサルティング契約が必要となります。

Back To Top

プラグインにログを設定する方法はありますか?

当社のサーバー上のログファイルへのアクセスは許可されていません。 このため、ログや警告には外部サービスを使用する必要があります。 Logentries または Papertrailの使用をお勧めします。 Enterprise Cloudをご利用中のお客様は、弊社にご連絡ください。お使いのプライベートクラウドに、ご希望のロギングサービスを設定いたします。 Logentriesをご希望の場合には 設定済みのログトークンを連絡してください。 Papertrailをご希望の場合には、カスタムURLとポートを連絡してください。

Back To Top

ログエントリートークンを取得する方法は?

Logentriesアカウントを作成し、以下の3つの手順にしたがってください:

  1. 「Logs"/"Add New Log」を選択してください。
  2. 「Libraries"/".NET」を選択してください。
  3. ログセットに名前を入力します。
  4. 「Create Log Token」をクリックします。
  5. 「Finish & View Log」をクリックします。
  6. 新しいログセットを選び、「Setting」タブを選択します。トークンを参照できるようになります。
  7. メールでトークンを送信してください。

Back To Top

Papertrail URLを取得する方法は?

Papertrailアカウントを作成し、以下の手順にしたがってください:

  1. Add "System" 「System」を追加します。
  2. 次のページの上部に「Your logs will go to logs6.papertrailapp.com:12345 and appear in Events.」といった文言が表示されます。
  3. メールでそのURLを送信してください。

Back To Top

新たなプラグインバージョンをリリースするために推奨される方法とは?

現在、Photonのプラグインはサイド・バイ・サイドのアセンブリバージョニングのみをサポートしています:AppIDごとに1つのプラグインDLLバージョンです。

新しいプラグインバージョンを展開するには、以下の2つの方法を推奨します:

A. 「互換性のある」プラグインの展開:新たなクライアントバージョンは不要です。

  1. 新しいバージョンのプラグインアセンブリをアップロードします。
  2. AppIDをステージングする際:新たなバージョンが予期されたとおりに動作している点を確認してください(推奨)。
  3. 新たなプラグインアセンブリバージョンを使用するため、本番のAppID設定を更新します。

B. 「互換性のない」プラグインの展開:新たなクライアントバージョンが必要です。

  1. プラグインアセンブリの新たなバージョンをアップロードします。
  2. 新たな本番のAppIDを設定します。
  3. 新たなプラグインアセンブリバージョンを使用するため、新たな本番のAppIDを設定します。

さらに高度なテクニックは以下のとおりです:

実際のゲームロジックは明示的に読み込まれる別のDLLからですが、コアサーバーアップデートループをもつプラグインDLLを構築することも可能です。 バージョンごとにゲームロジックは1つ以上のDLLを持つ必要がありますが、コアプラグインDLLは更新されるべきではありません。 コアプラグインDLLは、クライアントバージョンにもとづき適切なゲームロジックDLLを読み込みます。 これは、完全な互換性のためにサーバーサイドコードをクライアントサイドコードにマッピングするのと同様です。 これによって、プラグインの互換性のあるバージョンアップデートが可能になります: このため、新たなプラグインバージョンがリリースされた際にクライアントにアップデートを強いる必要がありません。 ゲームロジックDLLをバージョンごとに個別のフォルダ、同じフォルダ内でバージョン内で異なる名前で格納することができます。

Back To Top

プラグイン内に静的なフィールドを使用できますか?

ルーム間やアプリケーション間で、同じプラグインが共有されます。 同じプラグインクラスの静的フィールドも、同様に共有されます。 静的フィールドの使用を回避できない場合、2つのアプリケーションで同じプラグインアセンブリの使用を回避するための方法は以下のとおりです:

  1. 異なる2つのプラグイン名の下に、同じプラグインファイルをアップロードします:

    a- 名前Xでプラグインアーカイブをアップロード b- 名前Yでプラグインアーカイブをアップロード

  2. 2つのアプリケーションに、「Path」以外は同じ設定を適用:

    a- プラグインXを使用するようアプリAを設定:"{customerName}\X" b- プラグインYを使用するようアプリBを設定:"{customerName}\X"

Back To Top

その他

プラグインがRemoveActorを実行した際に、特定の理由を取得する方法は?

現在、弊社はクライアントに int または string型の理由を送信しません。 クライアントを切断する前に、カスタムイベントを使用してクライアントに通知をおこなうことができます。 たとえば、理由とともにカスタムイベントを送信し、タイマーを使用してRemoveActor 200ms laterをスケジュールすることも可能です。

Back To Top

クライアントSDKはカスタム型を登録することにより、シリアル化の拡張に対応します。サーバー上でこれらの型を非シリアル化する方法は?

クライアントSDKと同様に、カスタム型は以下のように登録できます:

PluginHost.TryRegisterType(type: typeof (CustomPluginType), typeCode: 1, serializeFunction: SerializeFunction, deserializeFunction: DeserializeFunction);

詳細は プラグインマニュアルの「カスタム型」セクションを参照してください。

Back To Top

.DLLのファイルサイズには上限がありますか?

いいえ。ただし、弊社はこのファイルはそれほど大きくはないと考えています。

Back To Top

PhotonプラグインでPUNのPhotonNetwork.ServerTimestamp を取得する方法は?

Environment.TickCountを使用します。

ドキュメントのトップへ戻る