1時間でわかるPlugin開発と
Enterprise Cloudの詳解
Photon運営事務局
シニアテクニカルアドバイザー
並木 健太郎
アジェンダ
• Photonの外部連携方法
• Pluginとは、その詳細
• Enterprise CloudとPlugin
Photonの外部連携方法
Photonのしくみ
• すべてのクライアント(=プレ
イヤー)はサーバーへ接続
する
• サーバーはクライアント間
の通信を仲介する役割
Photon
Client Client Client
SDK SDK SDK
大前提として…
• Photonはストレージ機能などは一切持ってい
ません
• アカウント管理などで何かしらのストレージが
必要になる場合が一般的
• データ保存に関しては、今まで通りWebサー
ビス&ストレージ(DBなど)で作ってください
WebサービスとPhoton
• WebサービスとPhotonは
必ずしもつなげる必要は
ありません
• Webサービスでマルチプ
レイの準備をして、
Photonでマルチプレイを
行い、その結果をWeb
サービスに戻せば基本
的にはOK
Client
Client
Web Service準備
Client
Client
Photonマルチプレイ
Client
Client
Web Service結果
でもそれじゃ不安…
• マルチプレイ中の状況を把握したい
• ゲームのコントロールをサーバー側から行いた
い
• チート対策をしたい
プレイ中にPhotonとの連携が
必要になる場合も!
Photonの外部連携方法
• Webhooks & WebRPC
• Photon Serverでカスタマイズ
• Pluginでのカスタムコード実装
Webhooks & WebRPC
• ルーム内でのイベント発生時(ルーム作成、
入室、プロパティ設定など)に予め設定してお
いたWebサービスを呼び出すことができる
• 発生源、情報はPhoton -> Webサービスの片
方向(WebRPCの情報は逆も可)
• Photonのサーバー側は設定するだけでコー
ディングの必要性なし
Photon Serverでカスタマイズ
• Photonのサーバー側アプリに独自コードを入
れることにより、あらゆる挙動を変更したり、
ゲーム独自の動作をさせることが可能
• 自前の運用が必須、アップデートの管理など
もお客さま自身で行う必要あり
• ルームだけでなくロビーもカスタマイズ可能
Pluginでのカスタムコード実装
• Webhooksと同様にルーム内のイベント発生
時にコールバックとして呼ばれ、サーバー内
でカスタムコードを動かすことが可能
• 基本はイベントドリブンになるが、タイマーを
使うことにより主体的に動くことも可能
• ルーム内でのみ動作
自由度と手軽さ、運用負荷
• 自由度
Webhooks << Plugin < Serverカスタマイズ
• 手軽さ
Serverカスタマイズ << Plugin < Webhooks
• 運用負荷
Webhooks << Plugin <<< Serverカスタマイズ
Pluginとは、その詳細
Pluginとは
• .NET(C#)のDLL
• Photon ServerのLoadBalancingアプリの上で
動作し、ルーム内イベントで動く
• ひとつのアプリで使えるPluginは1DLLだが、
1DLL内に複数のPluginを実装することは可能
Pluginの内部構造
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.
PluginFactory
• Pluginのインスタンスを生成するためのクラス
• HiveよりRoom生成時に呼ばれる
– 実際に呼ばれるのはCreate()メソッド
– ここで指定されたPlugin名やconfigを受け取る
• 指定された情報を元にPluginのインスタンス
を生成し、戻り値として返すのが仕事
最小実装例
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;
}
}
}
なんでFactoryがいるの?
• Pluginを1つだけ動かすなら不要でした
• 複数のPluginをサポートする0.9より実装
• Plugin名を見て生成するインスタンスを分ける
必要がある
• Plugin生成を柔軟に対応できる
ClientとPlugin
• Room作成時、RoomOptions.Pluginsを設定する
ことによりPluginのリクエストが可能
– RoomOptions.Plugins = new string[] { "SomePlugin" };
• 配列になっていますが、現在は1つ目のみサ
ポート
• PluginFactoryで失敗した場合は、Clientに
PluginMismatchのエラーが返る
Pluginの実クラス
• IGamePluginを実装する
• 実際は最低限を実装している
Photon.Hive.Plugin.PluginBase
を継承して実装するのがおすすめ
– 必要なメソッドだけ実装することが可能
プロパティ
• Name: Plugin名
– ゲーム開始後、ClientがどのPluginで動いているかを
確認する
• Version: Pluginのバージョン
– 同上。設定側で決めることも可能
• PluginHost: PluginのホストI/F
– Hive側とのやりとりを行うクラス
各コールバックの説明
• ICallInfoの説明が必要なので、もう少し待って
ください…
ICallInfo
• 各コールバックのパラメータはICallInfoをベー
スに作られています
• 実際はICallInfoからそれぞれのコールバック
毎に再定義されています
– 例: ICreateGameCallInfo : ICallInfo
ICallInfoの重要な仕事
• リクエストデータなどにアクセスするため
– ICallInfo.Request
• このリクエストを処理するかどうかをHiveに伝
える
– ICallInfo.Continue(), Cancel(), Fail(), Defer()
ICallInfoのMethods
• Continue(): 処理継続
– 通常通り処理します
• Cancel(): 静かに破棄
– 処理は中断、クライアントへのエラー通知なし
• Fail(): エラー
– 処理は中断、エラーがクライアントに返される
• Defer(): 処理を遅延
– 処理を一旦遅らせ、後で再度判断を行う
どう使うの?
• Fail()
– Room作成時に条件を満たさないユーザーのRoom作
成を拒否する(Room参加時も同様に)
• Cancel()
– 不正なイベントが送られてきたので、破棄させる
• Defer()
– 外部へHTTPアクセスする場合で、レスポンスの内容
を確認してから処理する
コールバック一覧
• BeforeCloseGame()
• BeforeJoin()
• BeforeSetProperties()
• OnCloseGame()
• OnCreateGame()
• OnJoin()
• OnLeave()
• OnRaiseEvent()
• OnSetProperties()
• OnUnknownType()
• SetupInstance()
Room作成・入室
• Roomが存在しない場合
– OnCreateGame()
• Roomが存在する場合
– BeforeJoin()
• 入室させる前に情報を収集してOnJoin()で判断が可
能
– OnJoin()
Room退出・削除
• RoomからPlayerが退出した時
– OnLeave()
• RoomがServer上のメモリから削除される時
(EmptyRoomTTL経過後)
– BeforeCloseGame()
– OnCloseGame()
イベント受信・プロパティ設定
• イベント受信
– OnRaiseEvent()
• httpForwardのフラグに関わらず送信される
• Cancel()も可能
• プロパティ設定(Room, Player共通)
– BeforeSetProperties()
• ここでCancel()が可能
• ここでContinue()すると、プロパティの設定が行なわれる
– OnSetProperties()
Pluginの準備
• SetupInstance()
– PluginFactory()から呼ばれる
– Pluginの初期化を行い、利用できる状況にする
Pluginのインスタンス
• PluginのインスタンスはRoom毎に作られる
• Roomの新規作成か復元時に生成され、Roomか
ら全員退出しTTLを超えるまで存在
• SetupInstance()とOnCreateGame()は同じようなタ
イミングで呼ばれますが、全く違うものです
– SetupInstance()はPluginの初期化
– OnCreateGame()はRoom作成処理
スレッドモデル
• Pluginのインスタンス毎
• 1Room内は非同期アクションを含め1スレッド
なので、Room内でスレッドを意識する必要は
なし
• Roomをまたいで共有メモリなどを使う場合は
注意を
Pluginの中でできるアクション
• イベント送信
• タイマー
• HTTPアクセス
• プロパティ設定
• キックアウト
イベント送信
• IPluginHost.BroadcastEvent()を使って送信
• ターゲット指定により2つのオプション
– 送信先のActorNrのListを渡す
– targetGroupで送信先を指定する
• senderActorを0にするとServerから送られたと
Clientは認識
• イベントコードやデータの扱いはクライアントから
の扱いと同様
使用例
public void TimerAction() {
...
PluginHost.BroadcastEvent(ReceiverGroup.All, 0, 0, 1, new Dictionary<byte, string>
{ 1, "test" }, 0);
}
class TestPlugin : PluginBase {
...
this.BroadcastEvent(2, new Directory<byte, string> { 1, "params" });
タイマー
• 1回のみと繰り返しの2種類を用意
• Actionを指定して、初回起動までの時間、繰
り返しの場合は2回目以降の時間を指定すれ
ばOK
使用例
public override void BeforeSetProperties(IBeforeSetPropertiesCallInfo info) {
PluginHost.CreateOneTimeTimer(
() => info.Continue(),
2000);
info.Defer();
}
public void TimerAction() { ... }
object timer = PluginHost.CreateTimer(this.TimerAction, 2000, 1000);
...
PluginHost.StopTimer(timer);
HTTPアクセス
• 外部へのHTTPアクセスは
IPluginHost.HttpRequestを利用してください
• HttpRequestクラスでリクエストを構築し、
IPluginHost.HttpRequestで送信
• 同期、非同期どちらも可能です
実装例-非同期
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();
}
実装例-非同期 (続き)
public override void OnHttpRequest(IHttpReponse response, object userState) {
ICallInfo info = userState as ICallInfo;
...
if (info.IsDeffered) {
info.Continue();
}
}
実装例-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);
プロパティ設定・キックアウト
• Plugin内からのカスタムプロパティの設定が
可能です
– IPluginHost.SetProperties()
• キックアウト
– IPluginHost.RemoveActor()
Pluginのマニュアルについて
• その他詳細については、下記をご覧ください
• http://doc.photonengine.com/ja-
jp/onpremise/current/plugins/manual
• 現在英語になっておりますが、間も無く日本
語化予定です、少々お待ち下さい
Plugin TIPS
• Namespaceは自由に設定してください
– が、Plugin内では統一してください
• Plugin名にDefaultは使えません
• Pluginの名前はクラス名と合わせておくのが
わかりやいでしょう
開発を始めるにあたり
• 開発はPhoton ServerのSDKページにある、
Plugin SDK
をダウンロードして、Webhooksのソリューショ
ンとプロジェクトをコピーしてください
サンプル
• サンプルは、Server SDK (Plugin SDKでない)に
ある、LoadBalancingソリューション内の
TestPluginsプロジェクトがお勧めです
• 十数個のPluginを1つのDLLでまとめているの
で、複数Pluginのサンプルとしてもお勧めです
Pluginでの実装範囲
• Photon内部で完結する処理はPlugin内にて実装
– 特定のイベントを受信したら、プロパティを設定する
– 定期的に情報を更新してイベントを発生させる
• 外部ストレージが絡む場合などは処理そのもの
は外部で行い、HTTPでアクセス
– 直接DBにアクセスなどは決してお勧めしません
Pluginでの実装範囲
Photon
Plugin Web Server
DB
OnSetProperties
値チェック
⇨ここで実装
OnJoinRoom
参加者
チェック&記録
⇨HTTPで呼ぶ
参加者
チェック&記録
⇨ここで実装
Pluginのメリット
• Photon Serverのコードと、カスタムコードを完
全に分離することが可能
• 独立してデプロイができ、互いに干渉せずに
アップデートも可能!
• Photon Serverをご検討でも、ぜひPluginでカ
スタマイズしてみてください!
Enterprise CloudとPlugin
Pluginのデプロイ
• 各サーバーにPlugin DLLを設置すればOK
• Photon Serverの再起動は必要です
• 設定の変更はXMLの設定ファイルを変更する
必要あり
Pluginで運用負荷は減りますが…
• 多くのサーバーがある場合、Plugin DLLをアッ
プデートするのは面倒
• Plugin設定を1台ずつ変更するのも面倒…
もっと楽しませんか?
Enterprise Cloudとは
• Photon Cloudの上位サービス
• Private Cloudとして、サーバーを専有
• 複数のタイトルでの利用も可能
• クラウドサービスなので、
サーバー運用不要
• 運用体制も万全
Enterprise Cloudでのデプロイ
• PluginのDLLなどをZIPで固めて、PowerShellの
ツールでアップロードすれば完了!
• 複数バージョンに対応、適用はダッシュボード
でVersionを切り替えるだけ、ロールバックも
簡単
• Photon ServerのPluginそのまま使えます
Enterprise Cloudでの設定
• ダッシュボード上で、設定値を変更すれば反
映される
ステージング対応
• アプリケーション(AppID)毎にPluginの設定を
変更可能
• ステージング用AppID、本番用AppIDを分ける
ことにより、ステージング環境で十分テストを
して、その後本番に適用させることも可能
Cloud vs. Enterprise Cloud
Cloud
• Publicサービス (共有)
• 10,000CCUまで
• Webhooks対応
• 複数タイトル共有不可
• サーバー設定変更不可
Enterprise Cloud
• Privateサービス (専有)
• CCU上限なし
• Webhooks & Plugin対応
• 複数タイトル共有可能
• サーバー設定変更可能
Enterprise Cloud + Plugin
• PhotonもPluginも運用フリー!
• ClientとPluginの開発に注力できます!
• 開発工数、運用工数を削減して、コンテンツ
開発に注力してください!
まとめ
今後の予定
• 6/4(土) Photonってぶっちゃけどないやねん!!CCSがはじ
めてPhotonを使ってみた話@GMO Yours (大阪)
• 6月(予定) モンスターストライク運営のXFLAGさまと合同勉
強会@GMO Yours (渋谷)
• 7/5(火) GTMF大阪@グランフロント内
7/15(金) GTMF東京@秋葉原UDX
Marmalade/Cocos2d-x & Photonの最新事例
• 8/24-26 CEDEC 2016
• その他も続々開催予定!
Photon SNSアカウント
• Twitter
– @PhotonCloudJP
• Facebook
– https://www.facebook.com/photoncloudjp/
• ヘルプセンター
– https://support.photonegine.jp/hc/ja
まとめ
• Pluginはロジック組み込みを簡単にします!
• Photon Enterprise Cloudは運用フリーで柔軟
性の高いクラウドサービスです!
• Photon Enterprise Cloud + Pluginは最強の組
み合わせです!
• Photon ServerでPluginも有効です!
ありがとうございました!
develper@photonengine.jp

【Photon勉強会】FFGMでも採用!1時間でわかるPlugin開発とEnterprise Cloudの詳解