Successfully reported this slideshow.
Your SlideShare is downloading. ×

【Photon勉強会】1時間でわかるプラグイン開発とその実際(2017/3/23講演)

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 91 Ad

More Related Content

Slideshows for you (20)

Similar to 【Photon勉強会】1時間でわかるプラグイン開発とその実際(2017/3/23講演) (20)

Advertisement

Recently uploaded (20)

【Photon勉強会】1時間でわかるプラグイン開発とその実際(2017/3/23講演)

  1. 1. 1時間でわかるプラグ イン開発とその実際 Photon運営事務局 シニアテクニカルアドバイザー 並木 健太郎
  2. 2. アジェンダ • Photonの外部連携方法 • Pluginとは、その詳細 • Enterprise CloudとPlugin • デモ・ハンズオン • ハンズオン内容解説 • まとめ 2
  3. 3. Photonの外部連携方法 3
  4. 4. Photonのしくみ • すべてのクライアント(= プレイヤー)はサーバーへ 接続する • サーバーはクライアント 間の通信を仲介する役割 4 Photon Client Client Client SDK SDK SDK
  5. 5. 大前提として… • Photonはストレージ機能などは一切持っていま せん • アカウント管理などで何かしらのストレージが 必要になる場合が一般的 • データ保存に関しては、今まで通りWebサービ ス&ストレージ(DBなど)で作ってください 5
  6. 6. WebサービスとPhoton • WebサービスとPhoton は必ずしもつなげる必 要はありません • Webサービスでマルチ プレイの準備をして、 Photonでマルチプレイ を行い、その結果を Webサービスに戻せば 基本的にはOK 6 Client Client Web Service 準備 Client Client Photonマルチプレイ Client Client Web Service 結果
  7. 7. でもそれじゃ不安… • マルチプレイ中の状況を把握したい • ゲームのコントロールをサーバー側から行いたい • チート対策をしたい プレイ中にPhotonとの連携が 必要になる場合も! 7
  8. 8. Photonの外部連携方法 • Webhooks & WebRPC • Photon Serverでカスタマイズ • Pluginでのカスタムコード実装 8
  9. 9. Webhooks & WebRPC • ルーム内でのイベント発生時(ルーム作成、入 室、プロパティ設定など)に予め設定しておい たWebサービスを呼び出すことができる • 情報はPhoton -> Webサービスの片方向 (WebRPCの情報は逆も可) • Photonのサーバー側は設定するだけでコーディ ングの必要性なし 9
  10. 10. Photon Serverでカスタマイズ • Photonのサーバー側アプリに独自コードを入れ ることにより、あらゆる挙動を変更したり、 ゲーム独自の動作をさせることが可能 • 自前の運用が必須、アップデートの管理なども お客さま自身で行う必要あり • ルームだけでなくロビーもカスタマイズ可能 10
  11. 11. Pluginでのカスタムコード実装 • Webhooksと同様にルーム内のイベント発生時 にコールバックとして呼ばれ、サーバー内でカ スタムコードを動かすことが可能 • 基本はイベントドリブンになるが、タイマーを 使うことにより主体的に動くことも可能 • ルーム内でのみ動作 11
  12. 12. 自由度と手軽さ、運用負荷 • 自由度 Webhooks << Plugin < Serverカスタマイズ • 手軽さ Serverカスタマイズ << Plugin < Webhooks • 運用負荷 Webhooks << Plugin <<< Serverカスタマイズ 12
  13. 13. Pluginとは、その詳細 13
  14. 14. Pluginとは • .NET(C#)のDLL • Photon ServerのLoadBalancingアプリの上で動 作し、ルーム内イベントで動く • ひとつのアプリで使えるPluginは1DLLだが、 1DLL内に複数のPluginを実装することは可能 14
  15. 15. Pluginの内部構造 15 Hive PluginPluginFactory : IPluginFactory var plugin = new HogePlugin(); return plugin; 1. 2. HogePlugin : PluginBase(IGamePlugin) { public OnCreate(...) { ... } } HogePlugin : PluginBase(IGamePlugin) { public OnCreate(...) { ... } } HogePlugin : PluginBase(IGamePlugin) { public OnCreate(...) { ... } } 3.
  16. 16. PluginFactory • Pluginのインスタンスを生成するためのクラス • HiveよりRoom生成時に呼ばれる – 実際に呼ばれるのはCreate()メソッド – ここで指定されたPlugin名やconfigを受け取る • 指定された情報を元にPluginのインスタンスを 生成し、戻り値として返すのが仕事 16
  17. 17. 最小実装例 namespace HogePlugin { public class PluginFactory : Photon.Hive.Plugin.IPluginFactory { public IGamePlugin Create(...) { var plugin = new HogePlugin(); if (plugin.SetupInstance(gameHost, config, out errorMsg)) { return plugin; } return null; } } } 17
  18. 18. なんでFactoryがいるの? • Pluginを1つだけ動かすなら不要でした • 複数のPluginをサポートする0.9より実装 • Plugin名を見て生成するインスタンスを分ける 必要がある • Plugin生成を柔軟に対応できる 18
  19. 19. ClientとPlugin • Room作成時、RoomOptions.Pluginsを設定する ことによりPluginのリクエストが可能 – RoomOptions.Plugins = new string[] { "SomePlugin" }; • 配列になっていますが、現在は1つ目のみサポー ト • PluginFactoryで失敗した場合は、Clientに PluginMismatchのエラーが返る 19
  20. 20. Pluginの実クラス • IGamePluginを実装する • 実際は最低限を実装している Photon.Hive.Plugin.PluginBase を継承して実装するのがおすすめ – 必要なメソッドだけ実装することが可能 20
  21. 21. プロパティ • Name: Plugin名 – ゲーム開始後、ClientがどのPluginで動いているかを 確認する • Version: Pluginのバージョン – 同上。設定側で決めることも可能 • PluginHost: PluginのホストI/F – Hive側とのやりとりを行うクラス 21
  22. 22. 各コールバックの説明 • ICallInfoの説明が必要なので、もう少し待って ください… 22
  23. 23. ICallInfo • 各コールバックのパラメータはICallInfoをベー スに作られています • 実際はICallInfoからそれぞれのコールバック毎 に再定義されています – 例: ICreateGameCallInfo : ICallInfo 23
  24. 24. ICallInfoの重要な仕事 • リクエストデータなどにアクセスするため – ICallInfo.Request • このリクエストを処理するかどうかをHiveに伝 える – ICallInfo.Continue(), Cancel(), Fail(), Defer() 24
  25. 25. ICallInfoのMethods • Continue(): 処理継続 – 通常通り処理します • Cancel(): 静かに破棄 – 処理は中断、クライアントへのエラー通知なし • Fail(): エラー – 処理は中断、エラーがクライアントに返される • Defer(): 処理を遅延 – 処理を一旦遅らせ、後で再度判断を行う 25
  26. 26. どう使うの? • Fail() – Room作成時に条件を満たさないユーザーのRoom作 成を拒否する(Room参加時も同様に) • Cancel() – 不正なイベントが送られてきたので、破棄させる • Defer() – 外部へHTTPアクセスする場合で、レスポンスの内容 を確認してから処理する 26
  27. 27. コールバック一覧 • BeforeCloseGame() • BeforeJoin() • BeforeSetProperties() • OnCloseGame() • OnCreateGame() • OnJoin() • OnLeave() • OnRaiseEvent() • OnSetProperties() • OnUnknownType() • SetupInstance() 27
  28. 28. Room作成・入室 • Roomが存在しない場合 – OnCreateGame() • Roomが存在する場合 – BeforeJoin() • 入室させる前に情報を収集してOnJoin()で判断が可能 – OnJoin() 28
  29. 29. Room退出・削除 • RoomからPlayerが退出した時 – OnLeave() • RoomがServer上のメモリから削除される時 (EmptyRoomTTL経過後) – BeforeCloseGame() – OnCloseGame() 29
  30. 30. イベント受信・プロパティ設定 • イベント受信 – OnRaiseEvent() • httpForwardのフラグに関わらず送信される • Cancel()も可能 • プロパティ設定(Room, Player共通) – BeforeSetProperties() • ここでCancel()が可能 • ここでContinue()すると、プロパティの設定が行なわれる – OnSetProperties() 30
  31. 31. Pluginの準備 • SetupInstance() – PluginFactory()から呼ばれる – Pluginの初期化を行い、利用できる状況にする 31
  32. 32. Pluginのインスタンス • PluginのインスタンスはRoom毎に作られる • Roomの新規作成か復元時に生成され、Roomか ら全員退出しTTLを超えるまで存在 • SetupInstance()とOnCreateGame()は同じよう なタイミングで呼ばれますが、全く違うもので す – SetupInstance()はPluginの初期化 – OnCreateGame()はRoom作成処理 32
  33. 33. スレッドモデル • Pluginのインスタンス毎 • 1Room内は非同期アクションを含め1スレッド なので、Room内でスレッドを意識する必要は なし • Roomをまたいで共有メモリなどを使う場合は 注意を 33
  34. 34. Pluginの中でできるアクション • イベント送信 • タイマー • HTTPアクセス • プロパティ設定 • キックアウト 34
  35. 35. イベント送信 • IPluginHost.BroadcastEvent()を使って送信 • ターゲット指定により2つのオプション – 送信先のActorNrのListを渡す – targetGroupで送信先を指定する • senderActorを0にするとServerから送られたと Clientは認識 • イベントコードやデータの扱いはクライアントから の扱いと同様 35
  36. 36. 使用例 public void TimerAction() { ... PluginHost.BroadcastEvent(ReceiverGroup.All, 0, 0, 1, new Dictionary<byte, string> { 1, "test" }, 0); } 36 class TestPlugin : PluginBase { ... this.BroadcastEvent(2, new Directory<byte, string> { 1, "params" });
  37. 37. タイマー • 1回のみと繰り返しの2種類を用意 • Actionを指定して、初回起動までの時間、繰り 返しの場合は2回目以降の時間を指定すればOK 37
  38. 38. 使用例 public override void BeforeSetProperties(IBeforeSetPropertiesCallInfo info) { PluginHost.CreateOneTimeTimer( () => info.Continue(), 2000); info.Defer(); } 38 public void TimerAction() { ... } object timer = PluginHost.CreateTimer(this.TimerAction, 2000, 1000); ... PluginHost.StopTimer(timer);
  39. 39. HTTPアクセス • 外部へのHTTPアクセスは IPluginHost.HttpRequestを利用してください • HttpRequestクラスでリクエストを構築し、 IPluginHost.HttpRequestで送信 • 同期、非同期どちらも可能です 39
  40. 40. 実装例-非同期 public override void OnRaiseEvent(IRaiseEventCallInfo info) { ... HttpRequest request = new HttpRequest() { Callback = OnHttpResponse, Url = "https://hogehoge.com/hogehoge", Async = true, UserState = info }; PluginHost.HttpRequest(request); info.Defer(); } 40
  41. 41. 実装例-非同期 (続き) public override void OnHttpRequest(IHttpReponse response, object userState) { ICallInfo info = userState as ICallInfo; ... if (info.IsDeffered) { info.Continue(); } } 41
  42. 42. 実装例-JSON string json = "..."; var stream = new MemoryStream(); var data = Encoding.UTF8.GetBytes(json); stream.Write(data, 0, data,length); HttpRequest request = new HttpRequest() { Callback = callback, Url = "https://api.hoge.com/api/json", DataStream = stream, Method = "POST", ContentType = "application/json" }; PluginHost.HttpRequest(request); 42
  43. 43. プロパティ設定・キックアウト • Plugin内からのカスタムプロパティの設定が可 能です – IPluginHost.SetProperties() • キックアウト – IPluginHost.RemoveActor() 43
  44. 44. Pluginのマニュアルについて • その他詳細については、下記をご覧ください • http://doc.photonengine.com/ja- jp/onpremise/current/plugins/manual • http://doc- api.photonengine.com/en/plugins/current/index.h tml 44
  45. 45. 名前空間、クラス名 • Namespaceは自由に設定してください – が、Plugin内では統一してください • Plugin名にDefaultは使えません • Pluginの名前はクラス名と合わせておくのがわ かりやいでしょう 45
  46. 46. 開発を始めるにあたり • 開発はPhoton ServerのSDKページにある、 Plugin SDK をダウンロードして、Webhooksのソリュー ションとプロジェクトをコピーしてください • 今日ご提供するPluginTemplateプロジェクトも 是非ご利用ください 46
  47. 47. サンプル • サンプルは、Server SDK (Plugin SDKでない)に ある、LoadBalancingソリューション内の TestPluginsプロジェクトがお勧めです • 十数個のPluginを1つのDLLでまとめているので、 複数Pluginのサンプルとしてもお勧めです 47
  48. 48. Pluginでの実装範囲 • Photon内部で完結する処理はPlugin内にて実装 – 特定のイベントを受信したら、プロパティを設定す る – 定期的に情報を更新してイベントを発生させる • 外部ストレージが絡む場合などは処理そのもの は外部で行い、HTTPでアクセス – 直接DBにアクセスなどは決してお勧めしません 48
  49. 49. Pluginでの実装範囲 49 Photon Plugin Web Server DB OnSetProperties 値チェック ⇨ここで実装 OnJoinRoom 参加者 チェック&記録 ⇨HTTPで呼ぶ 参加者 チェック&記録 ⇨ここで実装
  50. 50. Pluginのメリット • Photon Serverのコードと、カスタムコードを完 全に分離することが可能 • 独立してデプロイができ、互いに干渉せずに アップデートも可能! • Photon Serverをご検討でも、ぜひPluginでカス タマイズしてみてください! 50
  51. 51. Enterprise CloudとPlugin 51
  52. 52. Pluginのデプロイ • 各サーバーにPlugin DLLを設置すればOK • Photon Serverの再起動は必要です • 設定の変更はXMLの設定ファイルを変更する必 要あり 52
  53. 53. Pluginで運用負荷は減りますが… • 多くのサーバーがある場合、Plugin DLLをアッ プデートするのは面倒 • Plugin設定を1台ずつ変更するのも面倒… もっと楽しませんか? 53
  54. 54. Enterprise Cloudとは • Photon Cloudの上位サービス • Private Cloudとして、サーバーを専有 • 複数のタイトルでの利用も可能 • クラウドサービスなので、 サーバー運用不要 • 運用体制も万全 54
  55. 55. Enterprise Cloudでのデプロイ • PluginのDLLなどをZIPで固めて、PowerShellの ツールでアップロードすれば完了! • 複数バージョンに対応、適用はダッシュボード でVersionを切り替えるだけ、ロールバックも簡 単 • Photon ServerのPluginそのまま使えます 55
  56. 56. Enterprise Cloudでの設定 • ダッシュボード上で、設定値を変更すれば反映 される 56
  57. 57. ステージング対応 • アプリケーション(AppID)毎にPluginの設定を変 更可能 • ステージング用AppID、本番用AppIDを分けるこ とにより、ステージング環境で十分テストをし て、その後本番に適用させることも可能 57
  58. 58. Cloud vs. Enterprise Cloud Cloud • Publicサービス (共有) • 5,000CCUまで • Webhooks対応 • 複数タイトル共有不可 • サーバー設定変更不可 Enterprise Cloud • Privateサービス (専有) • CCU上限なし • Webhooks & Plugin対応 • 複数タイトル共有可能 • サーバー設定変更可能 58
  59. 59. Enterprise Cloud + Plugin • PhotonもPluginも運用フリー! • ClientとPluginの開発に注力できます! • 開発工数、運用工数を削減して、コンテンツ開 発に注力してください! 59
  60. 60. デモ・ハンズオン 60
  61. 61. ハンズオンの目標 • プラグイン開発を本格的に始められるまで • テンプレートとしてご用意しています • ここを覚えておけば、あとは自前のコードを書 くだけ! • マルチプラグインの実装もこれで理解できます 61
  62. 62. まずはダウンロード • Webページにある4つをダウンロード – Plugin Template プロジェクト – Photon Plugin SDK 4.0.29 – Photon Server SDK 4.0.29 – デモクライアント(いずれか) 62
  63. 63. Plugin SDKとPlugin Template展開 • Plugin SDKを実行して、 任意のフォルダに展開 • Plugin Templateのブロッ クを解除 • PluginTemplateを下記に 展開 – (plugin-sdk)¥src- server¥Plugins 63
  64. 64. Visual Studio起動 • Visual Studioを起動 – 空のソリューションとするために、ファイルから開 くのではなくスタートメニューで起動 • PluginTemplateプロジェクトをオープン – PluginTemplateフォルダにある PluginTemplate.csproj をオープン 64
  65. 65. ソリューション保存 • 一旦ソリューションを保存 • ソリューション名 – PluginTemplate • 保存先 – (plugin-sdk)¥src-server¥Plugins 65
  66. 66. プロジェクト設定変更 • PluginTemplateプロジェク トのプロパティを開く • デバッグのタブを選択 • 外部プログラムを再選択 – (plugin- sdk)bin_Win64¥PhotonSock etServer.exe • コマンドライン引数の最後 を変更 – bin_Win64 • 変更が終わったら保存 • aa 66
  67. 67. Plugin読み込み設定変更 • (plugin- sdk)¥deploy¥LoadBalancing¥GameServer¥bin¥ Photon.LoadBalancing.dll.configを開く • 254行目からのPluginSettingsを見つける • 256行目からのPluginを削除、Webページ通り記 載の内容に置換 67
  68. 68. ビルド & デバッグ開始 • ビルドを実行 • 下記メッセージが2つ出ればビルド成功 – 5個のファイルをコピーしました • 続いてデバッグを開始 – 停止せず動いていればOK • Windowsファイアウォールのメッセージが出た 場合は許可を 68
  69. 69. デモクライアント起動 • テストクライアント を起動 • 接続先は 127.0.0.1(localhost)の ままで • 使用Pluginの指定はお 好みで 69
  70. 70. デモクライアント操作 • Enterキーでイベント コード10を送信 • Spaceでイベントコー ド5を送信 • イベントを受信する と画面に表示 70
  71. 71. 動きの解説 71
  72. 72. 全体の構造 • PluginFactory • 2つのプラグイン – Plugin1 – Plugin2 72
  73. 73. PluginFactory • Pluginインスタンスを生成するPluginFactory • pluginNameを受け取って、該当するpluginのイ ンスタンスを生成 • pluginNameを細かく解釈して、Plugin名とパラ メータと分けて生成することも可能 73
  74. 74. Plugin1 • EventCode = 10を受信したら、EventCode = 20 のイベントを全クライアントに送信する • OnRaiseEvent()では基底クラスのメソッドを先 に呼んで処理を進めていますが、キャンセルな どを行う可能性があるなら、基底クラスのメ ソッドは呼ばないで 74
  75. 75. Plugin2 • SetupInstance()にてタイマー生成 • 間隔は最初1000ms、以後も1000ms • タイマーのコールバックメソッドtimerAction() にて、イベントを生成 • EventCodeは20からインクリメント、100まで いったら20に戻る 75
  76. 76. Plugin開発のTips 76
  77. 77. Plugin名 • 1タイトル内で全く挙動の異なるPluginが必要な ら、このテンプレートのように複数のPluginを 使い分けるほうが効率的 • Plugin名を工夫してパラメータを渡すことも可 能だが、インスタンスの再利用時に混乱しない よう、注意すること – Pluginが返すNameプロパティが同一の場合、Photon 内でインスタンスを再利用する場合もある 77
  78. 78. インスタンス再利用 • すでに生成済みかつルームが非アクティブ(=メ ンバー全員非アクティブ)で、要求Plugin名と Nameプロパティが一致する場合、インスタン スを再利用することがある • その場合、PluginFactoryやSetupInstance()が呼 ばれないので、それらが必ず呼ばれることを前 提にした実装にはしない 78
  79. 79. イベント処理 • OnRaiseEvent()は、Webhooksと違い全てのイ ベントにおいて呼ばれる • 本当に必要なイベントのみ検知し、監視・介入 を行うこと • Webhooksと同様、Request内のHttpFowardを見 てそのイベントだけ処理する方法も 79
  80. 80. ICallInfoのメソッド • ICallInfoのメソッドである Continue(), Cancel(), Fail(), Defer() は可能な限り早く呼び出してください • さもないと、Photon自身の処理に大きく影響し ます • 必要のないイベントは早急にContinue()で処理 継続を 80
  81. 81. PluginTemplateからの始め方 81
  82. 82. やるべきこと • PluginTemplateフォルダコピー • ファイル名変更 • 名前空間、クラス名変更 • プロジェクト設定変更 • Photon Server設定変更 82
  83. 83. フォルダコピー • (plugin-sdk)¥src-server¥Plugins¥ PluginTemplate フォルダを任意の名前で丸ごとコピー 83
  84. 84. ファイル名変更 • Plugin本体をクラス名に合わせてファイル名を 変更 – 1つだけなら、Plugin2.csは削除 84
  85. 85. 名前空間、クラス名変更 • PluginFactory、Plugin本体の名前空間を変更 – Photon配下でなくても全然OK – ただしDLL内は統一すること • PluginFactoryのクラス名はそのままを推奨 • Plugin本体は任意の名前で – Plugin名とクラス名は一致させておくと楽です 85
  86. 86. プロジェクト設定変更 • 「アプリケーション」タブ – アセンブリ名、既定の名前空間 – アセンブリ情報内 • タイトル、アセンブリバージョン、ファイルバージョン、GUID • 「ビルド イベント」タブ – ビルド後イベントのコマンドライン • 「デバッグ」タブ – 開始動作 - 外部プログラムの開始 86
  87. 87. Photon Server設定変更 • 68ページのPlugin読み込み設定変更と同様 87
  88. 88. まとめ 88
  89. 89. まとめ • Pluginはロジック組み込みを簡単にします! • Photon Enterprise Cloudは運用フリーで柔軟性 の高いクラウドサービスです! • Photon Enterprise Cloud + Pluginは最強の組み 合わせです! • Photon ServerでPluginも有効です! 89
  90. 90. Photon SNSアカウント • Twitter – @PhotonCloudJP • Facebook – https://www.facebook.com/photoncloudjp/ • ヘルプセンター – https://support.photonegine.jp/hc/ja 90
  91. 91. ありがとうございまし た! developer@photonengine.jp

×