Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ポコロンダンジョンズとリアルタイム通信 -クライアント編-
Search
CyberAgent SGE Engineer
May 20, 2016
Programming
0
280
ポコロンダンジョンズとリアルタイム通信 -クライアント編-
https://atnd.org/events/76070
の発表資料です
CyberAgent SGE Engineer
May 20, 2016
Tweet
Share
More Decks by CyberAgent SGE Engineer
See All by CyberAgent SGE Engineer
SREチームの立ち上げから5年間とこれから
sgeengineer
0
1.6k
サムザップにおけるNotionの 活用事例とPHPでのNotionAPIを利用した仕組み構築の紹介
sgeengineer
0
1.8k
Laravel OctaneをどうしてもPharで運用したい話
sgeengineer
2
2.3k
大規模Unityゲーム開発の設計事例 〜ドメイン駆動設計とDIコンテナを導入した一年を振り返る〜 / cedec2021-ddd
sgeengineer
2
13k
ロボットを動かすビジュアルプログラミングでできることはPHPでもできる!
sgeengineer
0
1.5k
PHP8版!Swooleのフレームワークを比べてみた
sgeengineer
1
2.5k
「戦国炎舞 -KIZNA-」で行ったAWSのコスト最適化の話
sgeengineer
0
1.7k
AirtestとPocoとOpenSTFによるUnity製スマートフォン向けゲームの実機自動テスト環境構築とその利用方法
sgeengineer
0
4.9k
PHPでgRPCって どこまでいけるの?
sgeengineer
0
4.7k
Other Decks in Programming
See All in Programming
たのしいSocketのしくみ / Socket Under a Microscope
coe401_
8
1.4k
技術を改善し続ける
gumioji
0
140
もう僕は OpenAPI を書きたくない
sgash708
6
1.9k
15分で学ぶDuckDBの可愛い使い方 DuckDBの最近の更新
notrogue
3
730
[JAWS DAYS 2025] 最近の DB の競合解決の仕組みが分かった気になってみた
maroon1st
0
140
機能が複雑化しても 頼りになる FactoryBotの話
tamikof
1
220
「個人開発マネタイズ大全」が教えてくれたこと
bani24884
1
270
CDK開発におけるコーディング規約の運用
yamanashi_ren01
2
260
LINE messaging APIを使ってGoogleカレンダーと連携した予約ツールを作ってみた
takumakoike
0
120
Learning Kotlin with detekt
inouehi
1
150
責務と認知負荷を整える! 抽象レベルを意識した関心の分離
yahiru
8
1.5k
.NET Frameworkでも汎用ホストが使いたい!
tomokusaba
0
200
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.3k
Large-scale JavaScript Application Architecture
addyosmani
511
110k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
11
1.3k
Writing Fast Ruby
sferik
628
61k
Rails Girls Zürich Keynote
gr2m
94
13k
Embracing the Ebb and Flow
colly
84
4.6k
Practical Orchestrator
shlominoach
186
10k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
134
33k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Adopting Sorbet at Scale
ufuk
75
9.2k
Transcript
ポコロンダンジョンズと リアルタイム通信 -‐‑ クライアント編 -‐‑ Grenge 袴田 大貴
自己紹介 • 袴田 大貴 (Hakamata Daiki) • 株式会社グレンジ所属 • ポコロンダンジョンズ
クライアントエンジニア • リリース前から現在まで https://www.facebook.com/D.hakamata
ポコロンダンジョンズ
アプリ紹介 • なぞるパズルRPG パズルブロック「ポコロン」をなぞって主人公を動かし、 敵を攻撃してダンジョンを攻略! • 1000種を超える装備, モンスター • 最大4人の協力プレイ「共闘」
None
アジェンダ 1. 構成 2. 同期方法 3. 具体例 4. 確率で発生する事象 5.
待ち合わせ 6. 再接続と強制同期 7. まとめ
1. 構成
構成図 curl (h+ps) WebSocket (wss) (詳細はサーバサイドの塚原さんの発表で…)
リアルタイム通信 n プロトコル WebSocket : ブラウザでは定番 UDP : MMOでよく使われる RUDP
: UDPとTCPの良いとこどり HTTP : ポーリング n ミドルウェア Node.js : すべての処理を自前で実装, JavaScript Photon : クラウドあり, C#, WIndowsServer モノビットエンジン : クラウドあり, C++, LinuxServer
クライアント構成 n ゲームエンジン Cocos2d-x v3.2.0 n 使用言語
ソケット通信 n iOS AZSocketIO [ SocketRocket, AFNetWorking ] n Android
Socket.IO-Client for Java [ Java-WebSocket ] どちらも独自に改造済み
AZSocket Socket.IO-‐‑Client for Java GRWebSocket ポコロンダンジョンズ 実装構成
発生した問題 • バックグラウンド時の通信維持 • ソケットライブラリのメモリリーク • ソケット切断後GC多発 • 特定端末(Nexusなど)専用対応 •
意図的な切断と偶発的な切断の区別 • 通信保証 (再送) • 再接続
ソケット通信Libの改修 n iOS host, port, pathによる接続先設定 SSL対応 切断/再接続処理 n Android
SSL対応 SSLContextのプロトコル複数対応 切断処理 (GC多発) JNI/マルチスレッド対応 イベント名+JSONデータ送受信
2. 同期方法
同期方法 n クライアント分散方式 サーバが中継, 各クライアントが処理 n イベント同期 特定のイベントをトリガとして同期 演算に必要なデータを送受信 なぞった!
中継役
その他の同期方法 n サーバ集中方式 入力をサーバに送信し、サーバが処理 結果を各クライアントに配信 n リプレイ再生 クライアント側は演算せず、再生のみ n フレーム同期
毎フレームに同期を行う
端末間の同期 • 盤面の色, 配置 • 敵の情報 • プレイヤー, 召喚モンスターの情報 •
被ダメ/与ダメ • ターン数 • ドロップ情報 全てをやり取りするとデータ量多い!
端末間の同期 • ポコダン は ターン制 → 他プレイヤーの操作を自端末で再現すればデータ量削減 (2, 4), (2,
5), (3, 6) をなぞった 再現します
通信保証 受領通知が来るまで一定間隔で再送 サーバ→クライアントの場合も同様 ①送信 ②受領通知 • 端末間ではなく端末-サーバ間で保証
3. 具体例
部屋生成〜クエスト開始 ①部屋生成要求 ②接続確立&部屋情報同期 n ホスト
部屋生成〜クエスト開始 ①部屋一覧要求 ②部屋参加要求 n ゲスト ③接続確立&部屋情報同期
クエストの流れ プレイヤーターン開始 なぞる A.スキル なぞったマスを 歩きながら攻撃 C.スキル 敵ターン開始 移動前行動 移動中行動
移動後行動
クエスト中 (送信) n ターンの操作権限者が送る情報 • プレイヤ番号 • 行動タイプ (なぞり/スキル/リタイア/コンティニュー) •
コマンドインデックス (送信情報のシーケンシャル番号) • (なぞり情報) • (使用したスキル情報)
プレイヤー : 2 コマンド : 0 タイプ : なぞり始め なぞり
: (1, 4) プレイヤー : 2 コマンド : 1 タイプ : なぞり中 なぞり : (2, 4) ・・・ プレイヤー : 2 コマンド : 5 タイプ : なぞり終わり
クエスト中 (受信) n なぞり始め 盤面を暗転 n なぞり中 なぞり情報を元に光るラインを再現 n なぞり終わり
なぞりルートを確定 「送信者側の端末で起きた事象を自身の端末で再現」
4. 確率で発生する事象は どうする? クリティカル, 回避, 状態異常 etc…
乱数(擬似乱数) 乱数生成器 シード値 : A 乱数列 x1, x2, x3, x4,
x5, … 乱数生成器 シード値 : B 乱数列 y1, y2, y3, y4, y5, … 同一のシード値で初期化すれば、同一の乱数列が得られる
乱数同期 乱数生成器 乱数生成器 乱数生成器 乱数生成器 シード:X 全端末で同じ乱数列
複数の乱数生成器 n 可能な限りズレを抑止するために乱数生成器は複数 キャラクター毎に専用の乱数生成器 演出用の非同期の乱数生成器
乱数生成器 n メルセンヌ・ツイスター <random>ヘッダ 決定的 周期が長い 一様分布 高速 GRRandomUtility とライブラリ化して使用
OSとSTL n iOS libc++ (LLVM C++ standard library) n Android
APP_STL := gnustl_static [Application.mk] C++標準ライブラリが異なるので、そのままではシード値 を同期しても生成される乱数列が異なる
OSとSTL n AndroidをiOSに揃える NDKのリファレンス APP_STL := c++_static (cocos2d-x v3.2の推奨NDKバージョンは r9d
ですが r10dを使用)
5. 待ち合わせ
待ち合わせ Ready Ready Ready 待ち合わせ開始をサーバに通知
待ち合わせ AllReady AllReady AllReady 部屋の人数分揃ったらクライアントに通知
6. 再接続と強制同期
意図的/偶発的な切断 n 意図的な切断 専用のイベントをサーバに送信してから切断 これによって偶発的な切断と区別が可能 ・偶発的切断の発生件数検証 ・ゲーム内の通知メッセージ出し分け
疎通ロスト判定 Verification Verification 1P 2P 3P 疎通確認データを送信
疎通ロスト判定 VerificationResult 疎通を確認できたプレイヤーリストが返却 VerificationResult VerificationResult 疎通確認プレイヤーリスト 1P, 3P
疎通ロスト判定 n 疎通ロストしたプレイヤーがターン操作権限を持ってい た場合、ターンをスキップする n (共通の仕様として)スキップ3回で部屋からキック マナーの悪いプレイヤーの排除 安定した通信環境のプレイヤーのプレイを保護
再接続 1. 偶発的切断発生 2. 一定時間、再接続を試みる 3. 再接続に成功したら、クエスト復帰 キャリア回線とWi-Fiの切り替わりなど瞬断は起こりうる 「通信は切れるもの」として対策をする
強制同期 n 検証用の盤面情報を相互に送受信し、差異があった場合 はホスト権限者の盤面に強制的に揃える n 中断セーブデータ シングルプレイの仕組み クエスト情報をJSONに書き出しファイルに保存 シングルプレイで使用している中断セーブデータを流用 差異が生じたらホストのデータに全員ロールバック
7. まとめ
まとめ n 複数のプレイヤの情報を互いに送受信しつつ整合性を保 つ、のがリアルタイム通信によるゲームのキモ n ゲーム性に合わせた技術/同期方式を選定するのが重要 n 通信時間がどうしても発生するので、データ量は可能な 限り削減する