Contenu connexe
Similaire à Cocos2d-xの深層 Cocos2d-x組み込みによるピュアAndroid/iOSアプリの外科手術的統合 (20)
Cocos2d-xの深層 Cocos2d-x組み込みによるピュアAndroid/iOSアプリの外科手術的統合
- 1. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-xの深層
2016/08/24 @ CEDEC 2016
久富木 隆一 (KUBUKI Ryuichi)
Cocos2d-x組み込みによる
ピュアAndroid/iOSアプリの
外科手術的統合
- 2. Copyright © GREE, Inc. All Rights Reserved.
本日お話する内容
2
1. 自己紹介
2. 前提の共有: Cocos2d-xとは何か
3. Android/iOSクライアント統合という問題
- 2-1. 問題の状況と目指すべきゴール
- 2-2. 統合案の検討と採用案
4. Cocos2d-x組み込みによるクライアント統合
- 3-1. Android/iOSアプリの構造
- 3-2. Cocos2d-xのAndroid/iOS実装の構造
- 3-3. Cocos2d-x組み込みの技術的詳細
- 3-4. これからのCocos2d-x
5. 総括
- 3. Copyright © GREE, Inc. All Rights Reserved.
自己紹介
3
• 久富木 隆一 (KUBUKI Ryuichi)
• グリー株式会社
• West Game事業本部
GREE International Entertainment(米国サ
ンフランシスコ)等、海外ゲーム事業を担当
- 4. Copyright © GREE, Inc. All Rights Reserved.
自己紹介
4
Crime City
• Android / iOS
• 2011-
• Over tens of millions
download globally
Modern War
• Android / iOS
• 2011-
• Over tens of millions
download globally
- 5. Copyright © GREE, Inc. All Rights Reserved.
自己紹介
5
• 久富木 隆一 (KUBUKI Ryuichi)
Twitter: @ryukbk
『ゲームアプリの数学
Unityで学ぶ基礎からシェーダーまで』
(SBクリエイティブ刊)
• リアルタイム3Dグラフィックスを成
り立たせている数学要素をUnityサン
プルプロジェクト付きで解説
• OpenGL ESレンダリングパイプライ
ンやGPUアーキテクチャー、モバイ
ル向け最適化も紹介
- 6. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-xとは何か
6
• Cocos2d
• iOS向けの2Dゲームエンジン(Objective-C,
Ricardo Quesada, 2008)
• Cocos2d-x
• Cocos2dのAPIを保持しつつ
Android/Windows向けに移植(C++, Zhe
Wang, 2010)
• Cocos2d-xの現在
• Cocos2d作者も合流した主流となり、APIを
独自発展。中国Chukong Technologiesを主
な支援者としてオープンソース開発中
- 7. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-xとは何か
7
• Cocos2d-xは完全にオープンソース
• Unityは完全にオープンソースではない
• Cocos2d-xは完全無料
• Unity、Unreal Engineは有料
メリット
デメリット
• Cocos2d-xにはベンダーサポートはない(コミュ
ニティはある)
• 3Dや開発環境など発展途上
- 8. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
8
Crime City
• Android / iOS
• 2011-
Modern War
• Android / iOS
• 2011-
• iOS/Androidクライアントを、別々のチーム
がそれぞれ独立して開発(ピュアObj-C/Java)
• 通信するサーバー、スタティックデータ(マ
スターデータ)は共通
• それ以外(ビュー/UI、ロジック)は全てプ
ラットフォーム別に独自実装
状況把握
- 9. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
9
• 問題1: 同じゲームの複数の実装
• 車輪の再発明
• Android/iOS開発者が別個にい
るためヘッドカウントが2倍
• Android/iOS実装間での見た目
や挙動の差異
- 10. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
10
• 問題2: データ駆動ではないデザイ
ンパイプライン
• エンジニアがUIやアニメーショ
ンの調整を実施
• エンジニアがステート遷移を
コードで実装
• スタティックデータの変更以外
エンジニアの助力なしに行えな
い
- 11. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
11
• 問題3: 将来にわたって安心(future-
proof)ではないレガシーアーキテクチャー
• 描画がOpenGL ES 1.1に留まる
• 新OSバージョンへの対応コスト
• 3D、パーティクル、物理、AIなどゲー
ムデザインに影響を与える技術要素の追
加困難
• Objective-CはSwiftに取って代わられる
• 開発者を探しにくい
- 12. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
12
1. 同じゲームの複数の実装
2. データ駆動ではないデザイ
ンパイプライン
3. 将来にわたって安心
(future-proof)ではないレ
ガシーアーキテクチャー
問題
- 13. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
13
よし、Android/iOSで
分かれているクライア
ントを1つに統合しよ
う!
結論
- 14. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
14
1. 単一の実装への統合
• Write Once, Run Everywhere
• ユニットテスト/テスト自動化が楽
2. データ駆動デザインパイプライン
• エンジニアリングリソースがボトルネックと
ならない
3. 将来にわたって安心(future-proof)なアー
キテクチャー
• 一般的なゲームエンジンの最新版を利用
• 既に流通しているソフトウェアコンポーネン
トの再利用
ゴール
- 15. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
15
1.なるべく早期のローンチを
2.なるべく移行をスムースに
3.なるべく低い金銭的コストで
4.なるべく低い開発者教育コストで
5.サーバーとスタティックデータは
現在のものを流用
6.オリジナルの見た目を踏襲
現実的な追加要件
- 16. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
16
1.保守的な案
• 現実的、低リスク、地味、
コード駆動、旧式
2.革新的な案
• 理想的、高リスク、派手、
データ駆動、モダン
2つの案
- 17. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
17
• 今回のゲーム(既存アプリ)内に、スク
リプトエンジン等を組み込むのと同様
に、Cocos2d-xゲームエンジンをまる
ごと組み込み(embed)
• 新フィーチャーのみCocos2d-xで開発
• 既存アプリのコードを原則再利用し、
必要に応じてCocos2d-x部分へ漸次移
植
保守的な案
- 18. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
18
1. 単一の実装への統合
• C++でAndroid/iOS向けに実装できる
• ただし既存アプリ部分とのブリッジAPIを実装
するコードは複雑になる
• ただし既存コード(Obj-C/Java)のメインテナ
ンスは必要
2. データ駆動デザインパイプライン
• Cocos Studio/Cocos Creatorが使える
3. 将来にわたって安心(future-proof)なアー
キテクチャー
• 最新のオープンソースゲームエンジン
保守的な案(Cocos2d-x組み込み)
- 19. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
19
• Unityへ移植
• 現在のサーバー&スタティックデータ
&アセットデータとの互換性を持つク
リーン実装
• 課金や通知など再実装/再検証コスト
が高い部分のみ既存アプリ実装をネイ
ティブプラグイン化して再利用
• データ駆動デザインを促進するUnity
アセットの利用
革新的な案
- 20. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
20
1. 単一の実装への統合
• C#でAndroid/iOS向けに実装できる
2. データ駆動デザインパイプライン
• Unity Editor中心の開発
• MarkUX: XMLによるMVVMでUI作成
• NodeCanvas: Behaviour TreeやHierarchical
State Machineで状態遷移作成
3. 将来にわたって安心(future-proof)なアー
キテクチャー
• 最新のトレンドを押さえたゲームエンジン
革新的な案(Unity移植)
- 21. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
21
• 保守的な案(Cocos2d-x組み込み)と
革新的な案(Unity移植)を3つのゴー
ルの達成度で比較した場合、革新的
な案の方が優位となった
• しかし、追加的要件も勘案すると、
保守的な案(Cocos2d-x組み込み)が
優位となったため、今回はそちらを
採用した
採用案
- 22. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
22
1. なるべく早期のローンチを
2. なるべく移行をスムースに
3. なるべく低い金銭的コストで
4. なるべく低い開発者教育コストで
5. サーバーとスタティックデータは現在のものを
流用
6. オリジナルの見た目を踏襲
Cocos2d-x組み込みはこれらの要件を満たす
1: (Cocos2d-x組み込みの技術さえ確立できれば)移植より早く済む。
2/5/6: 既存部分の流用が多いので問題が少ない。
3: Cocos2d-xは無料である。
4: 偶然今回のプロジェクトチームではCocos2d-x経験者が多かったので
問題とならなかった。
- 23. Copyright © GREE, Inc. All Rights Reserved.
Android/iOSクライアント統合という問題
23
• Unityのネイティブプラグインは独
自描画を行えるため、既存アプリ部
分をまるごとネイティブプラグイン
化することも考えられる
• しかし、Unity側に変更を加える必
要が出てくる可能性、既存アプリ部
分のビルドシステムとの親和性を考
え、今回は見送った
Unityへの既存アプリの組み込みはできないのか
- 24. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
24
• いきなり実装の詳細に入って行く前に、全体の
大まかな構造をイメージし、何ができそうかを
構想してみよう
• Cocos2d-x組み込みを思いついたのは、
Cocos2d-xの内部実装に自分が通暁していたか
らではなく、一般的なアプリを構成するゲーム
エンジンなら必ず一定の構造を内包しているは
ずなのでそれを再利用してやればよい、という
想定が自分の中にあったから
• ソースコードがある以上どうにでもなるという
楽観があった(OSの仕様に阻まれないかぎりは)
実装の詳細を追う前に
- 25. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
25
• 単純化して考えると、アプリは4つの要
素から成立している
1. イベントループ
2. ロジック
3. GLビュー
4. ネイティブUIウィジェットビュー
アプリの抽象的構造
- 26. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
26
• 常に動作しているイベントループが必要に応じて
異なるユーザー定義ロジック(Java/Obj-C)を実行
• 結果を、ネイティブUIウィジェットビュー(OS固
有のダイアログなどのUIウィジェット表示)、また
はアプリが独自にOpenGL ESでカスタム描画する
GLビューへ出力
アプリの抽象的構造
- 27. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
27
• 常に動作しているイベントループが必要
に応じて異なるユーザー定義ロジック
(C++)を実行し、実行結果を、アプリが
独自にOpenGL ESで描画するGLビュー
へ反映
Cocos2d-xの抽象的構造
- 28. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
28
• Cocos2d-xのGLビューが最前面に描
画される
Cocos2d-xを組み込んだアプリ構造の完成形
- 29. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
29
• UIView(とCALayer)の階層にGLビューを含む全
てのビューは属する
• Objective-C言語は、ファイル拡張子を.mか
ら.mmにするとObjective-C++としてCだけで
はなくC++コードを混ぜることができる
• Obj-Cの世界とC++の世界のメモリ空間は単一
• Obj-C - C++ - Obj-CまたはC++ - Obj-C -
C++の呼び出しとコールバック実行による処理
継続は、同期で、同じスタックフレーム上で起
こる
• メタファー: iOSアプリの世界は、モノリシック
(一枚岩)な世界である
iOSアプリの特性
- 30. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
30
• 1つのアプリが複数のActivityを内包する
• Activityは複数のFragmentを内包する
• ActivityはWindowとViewの階層を持つ
• ViewはGLビューであるGLSurfaceViewを含む
• Activity同士はIntentで通信しあう
• Activityが存在するJavaの世界(JVM)と、Linuxネイ
ティブのC/C++の世界(NDK)のメモリ空間は、分離さ
れており、越境(JNI)のコストは高い
• Java - C++ - JavaまたはC++ - Java - C++の呼び出
しとコールバック実行による処理継続は、非同期で、
異なるスタックフレーム/スレッド上で起こる
• メタファー: Androidの世界は、分散オブジェクト/
メッセージパッシング/疎結合マイクロサービスの世界
である
Androidアプリの特性
- 31. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
31
• Cocos2d-x自身は、これまで見てきた両プラット
フォームの特性を利用しつつ差異を吸収する形で
実装してある
• Cocos2d-xは、他アプリに組み込まれることを想
定した構造にはなっていないはず
• であれば、今回やるべきことの中心は2つ
1. 既存アプリとCocos2d-xとのブリッジコード
を実装してやる
2. Cocos2d-xのAndroid/iOS実装が他アプリの
存在を想定していない構造になっている部分
にパッチを適用(実際はほんの少しで済んだ)
Cocos2d-xのAndroid/iOS実装と組み込み
- 32. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
32
1. (AppDelegateはstatic変数領域に起動時
生成)
2. AppController#
didFinishLaunchingWithOptionsでGL
ビューであるCCEAGLViewを生成
3. 作成したGLビューをRootViewController
でビュー階層内に追加
4. Cocos2d-x側からGLビューに描画を行う
GLViewオブジェクトを生成
Cocos2d-xのiOS実装の起動フロー
- 33. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
33
1. Java: Cocos2dxActivityを生成
2. C++: platform/android下のjavaactivity-
android.cppをJNIで呼び出し、Cocos2d-xア
プリケーション本体であるAppDelegateをヒー
プ領域に生成
3. Java: GLビューであるGLSurfaceViewを生成
4. Java: Cocos2dxRendererを生成
5. C++: javaactivity-android.cppを呼んで、
Cocos2d-x側からGLビューに描画を行う
GLViewImplを生成
Cocos2d-xのAndroid実装の起動フロー
- 34. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
34
1. 既存アプリ内からCocos2d-xを起動してシーンを
作成し、全画面/モーダルダイアログとして表示
• シーン属性情報(例えばCocos2d-xダイアログの表示
サイズ)はJava/Obj-C側ではなくCocos2d-x側で持つ
2. 複数回表示を反復しても問題ないこと(冪等性)
3. アプリ起動直後からCocos2d-xオブジェクト
(AppDelegate)がC++側に存在すること
4. パフォーマンス低下を防ぐこと(速度/占有メモリ
/占有ストレージサイズ)
5. Cocos2d-xと既存アプリのモジュールを混在させ
た単一バイナリを生成するビルドプロジェクトを
構成
Cocos2d-x組み込み要件
- 35. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
35
1.既存アプリ側からCocos2d-xを
起動し指定したシーンを表示
2.Cocos2d-xから既存アプリ側の
Android/iOSネイティブ機能を
クロスプラットフォームの同じ
インターフェイスで利用するた
めのAPI
Cocos2d-x組み込みのために実装する機能
- 36. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
36
• iOSアプリの中からのCocos2d-x起動は、
Cocos2d-x自体のiOS実装同様に、シンプル
• Cocos2d-x起動フローと同様のGLビュー生成を、
既存アプリ内でCocos2d-xを起動したい場所から
呼び出すだけ
• GLビューをどの位置にどのサイズで生成するか
という点のみ解決できればよい
• [UIScreen mainScreen].applicationFrameで取得し
た画面サイズ(iOS 7以前はw/hが逆なので注意)と、
Cocos2d-xシーン側に設定したシーンサイズを使う
• Obj-C++なので既存アプリからCocos2d-x側の関数
を簡単に呼び出せる
組み込みCocos2d-x起動: iOS
- 37. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
37
• Cocos2d-xのAndroid版はActivity(Cocos2dxActivity)
として実装されているため、継承したクラスを作成し
挙動をオーバーライド。「アプリ起動直後から
AppDelegateがC++側に存在すること」という要件を
満たすために、起動直後に生成されるメインActivityと
してそのクラスを指定
• Cocos2d-xのライブラリ(libcocos2dcpp.so)をロード
し、C++側のメモリ空間にAppDelegateとGLViewが
生成されたら、C++側からJavaのCocos2dxActivity継
承クラス側にメッセージを送り、既存アプリのActivity
を起動して、既存アプリ起動プロセスを続行
• 既存アプリActivityの中からCocos2d-xのActivityを起
動する
• 異種システム間でどのようにメッセージを送る?
組み込みCocos2d-x起動: Android
- 38. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
38
• Cocos2d-x側と既存アプリ側とのブリッジAPIの
仕様を考える
• iOS側はモノリシックな構造だがAndroid側は分
散・疎結合の構造。両方を抽象化し単一のAPIで
制御するためには制限が大きい方に合わせるべき
• Android側の、メモリ空間が別れた非同期通信
モデルを基準とする
• Cocos2d-xシーンが主体となり、離れた世界(既
存アプリ側)のリソースをC++コードで制御する
ための、RPC(remote procedure call:遠隔関数
呼出)の仕組みが要る
Cocos2d-x側と既存アプリの通信
- 39. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
39
• Android
• JNI(Java Native Interface)で通信
• API呼び出し時にstd::function/ラムダ式のコール
バックを、boost::uuidで生成したUUIDをキーとして
マップへ登録。既存アプリ側は受け取っていたUUID
を返事を返す際に添えて返し、Cocos2d-x側は対応
コールバックを実行
• iOS
• Cocos2d-x -> 既存アプリ: Obj-C++のファイルにC
の関数を定義し、externで参照し呼び出し
• 既存アプリ -> Cocos2d-x: std::functionで渡された
コールバック関数を直接実行
Cocos2d-x側から既存アプリへのRPC
- 40. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
40
• 宣言: std::functionにコールバックとしてラムダ式を設定する
Cocos2d-x側から既存アプリへのRPC
• 実行: サーバーから返事が来るとラムダ式が実行される
- 41. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
41
• iOS
• 同じメモリー空間でC/C++の型が共通で存在してい
るのでデータ型の問題は存在しない
• Android
• C++とJavaの世界でデータを翻訳/交換するための合
意が必要
• 任意のデータをペイロードとしてラップし変換/交換
(marshalling)するための便利なバッグがあればよい
• 今回使ったもの
• boost::variant
using VariantValueType = boost::variant<int64_t,
double, std::string>;
• JSON (rapidjson::Document)
RPCとデータ型
- 42. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
42
• 既存アプリ側から文字列でCocos2d-xシーンを指定したい
• まずは可変長テンプレート引数を取れるC++テンプレー
ト(Variadic Templates)を使って、型リストの要素各々に
対してラムダ式を適用できるforEachを定義
文字列とデータ型の関連付け
- 43. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
43
• 登録しておいたシーンクラスのリストの要素に対し、
RTTIのtypeidで取得した型名文字列を
abi::__cxa_demangleでデマングルし、そのCocos2d-x
シーンを作成するScene::create関数のラムダ式と関連付
け(ラムダ引数のautoはC++14)
文字列とデータ型の関連付け
- 44. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
44
• 単にデータのやり取りをするだけでなく、
既存アプリ側の特定メソッドを実行するAPI
が必要になった
• 各プラットフォームのリフレクションの仕
組みが使える
• iOS
• NSInvocation#invoke
• Android
• Method#invoke
文字列とコードの関連付け
- 45. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
45
1. 既存アプリ側からCocos2d-xを起動し指定した
シーンを表示
2. Cocos2d-xから既存アプリ側のAndroid/iOSネイ
ティブ機能をクロスプラットフォームの同じイン
ターフェイスで利用するためのAPI
• これらの要素が最低限あればアプリ自体は
Cocos2d-xを組み込んだ状態で動くように
なっているが、実際にはそのアプリをビル
ドするためのプロジェクトを整備しなけれ
ばならない
Cocos2d-x組み込みアプリのビルド
- 46. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
46
• iOS
• 既存アプリのXcodeプロジェクトにCocos2d-xの
Xcodeプロジェクトcocos2d_libs.xcodeprojを入れる
• ただしXcodeプロジェクトのマージが難しいので
Cocos2d-xバージョンアップのたびに同じ作業が必要
• Android
• 既存アプリがモジュラーなgradleビルドシステムを採
用していたので、Cocos2d-xのAndroid Studio向けプ
ロジェクトをgradleモジュールとして差し込むことが
できる
• ただしC++部分はcocosコマンドでビルドする必要が
ある
• Android Studio 2のInstant Runとは相性が悪い
Cocos2d-x組み込みアプリのビルド
- 47. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
47
• Cocos2d-xのビューを、全画面ではなく画面の1部に表示
• 矩形ではなく、丸みのある角など自由な形状に
• フレームバッファーをアルファ値を持てるフォーマット
にする
• iOS
• CCEAGLViewでeaglLayer.opaque = NO、
pixelFormatをkEAGLColorFormatRGBA8に
• AndroidはそのままでOK
• Cocos2d-x側でそもそも黒く塗りつぶしていたので透明
に替える
• FrameBufferで_clearColor(Color4F(0, 0, 0, 0))、
Rendererで_clearColor.a = 0.0f
Cocos2d-xシーンのモーダルダイアログ表示
- 48. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
48
• Cocos2d-xのActivityを表示していると、背後に回った既
存アプリのActivityがOSによって制御できないタイミン
グでkillされてしまう
トラブルシューティング: Android Activity問題
• AndroidManifestで
@android:style/The
me.Translucent.NoTit
leBar.Fullscreenを指
定し背後の既存アプリ
Activityが見えるよう
にしてやればkillされな
い(全画面表示でも)
- 49. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
49
• HTC J Butterfly(HTV31)上でのリリースビルドのみで、
OpenGL ESのコンテクストがおかしいことによるエラー
が起こる(call to OpenGL ES API with no current context)
• Cocos2d-xのAPIを操作しOpenGL ESコンテクストを操
作する可能性のあるJNI呼び出しは、全て
GLSurfaceView.queueEvent経由の呼び出しとして
Cocos2d-x描画用スレッドで実行されるように
• 逆に、Androidのビュー階層をJNIから操作する場合は
Handler(Looper.getMainLooper())でUIスレッドにポス
ト
• Cocos2d-x側では、AndroidからJNIで受けたものは
performFunctionInCocosThreadで実行
トラブルシューティング: Androidスレッド問題
- 50. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
50
• アプリ起動時にAppDelegateのみ初期化しているものの、
Android版Cocos2d-xは元々バックグラウンドからの復帰
時にGLSurfaceViewを再生成するようになっておりその
処理がCocos2d-xビューを生成時にも必要なため、重い
初期化処理が走ることにより表示されるまで時間がか
かっていた
• Cocos2d-xは内部で使っているシェーダープログラムを
全て起動時に初期化しており、parseUniforms()と
glLinkProgramが特に重かった
• 3D向けなど使わないシェーダーの初期化を省略
• 今後シェーダーの利用時に初期化されるようになるかも
https://github.com/cocos2d/cocos2d-x/issues/15637
トラブルシューティング: Androidシェーダー問題
- 51. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
51
• Cocos2d-xビュー作成時は既存アプリGLビューのレンダ
リングループを止める
• Cocos2d-xビュー終了時には、Director::endを呼ぶと次
のフレームで呼ばれるGLViewImpl::end内で、GCDで
dispatch_asyncした先で、GLコンテクスト(今誰が描画
しているのか)を既存アプリのものに復帰
• Cocos2d-xと既存アプリのGLコンテクストの競合は起
こっていないはずにもかかわらず、Cocos2d-xを起動し
て閉じた後、既存アプリのテクスチャーが時々乱れた
• Cocos2d-xビュー作成前に開始されていた既存アプリの
テクスチャー非同期ダウンロードジョブが、ダウンロー
ド完了時(Cocos2d-x起動中)にglBindTextureなどGLの
関数を呼び出してしまっていたのでスキップするよう変
更
トラブルシューティング: iOSテクスチャー問題
- 52. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
52
• C++ラムダ式での変数キャプチャには注意
• サーバー通信などをCocos2d-xシーンからブリッジAPIを
経由して行うと、時間が経ち結果が帰ってきた時には元
のシーンが消滅しており、コールバックのラムダ式内に
キャプチャされたシーンのthisポインタが無効になってい
る場合がある
• staticなSceneFactoryでシーン毎にUUIDを発行して
同一性を保証し、シーンが存在しない/そのシーンが
発行していないAPI実行の結果が来た時は弾く
• 参照キャプチャ(&)を使うとスタック変数がキャプチャさ
れてしまい、iOSではスレッドを分けない限り原則として
同一スタックフレーム上でブリッジAPIが最後まで実行さ
れるので問題ないが、Androidではコールバックのスタッ
クフレームが異なり無効なアドレスを参照して落ちる
トラブルシューティング: シーンライフサイクル問題
- 53. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
53
• 透明領域を少なくして描画負荷を抑えるために、
Cocos2d-xのGLビューのサイズを、Cocos2d-x
内部で生成するシーンのサイズと同じにして既存
アプリ側から生成する仕様とした
• つまり、GLビューのサイズは端末画面サイズ
より多くの場合小さくなる
• この仕様により、Cocos2d-x側で全画面表示した
場合に行ってくれるスケーリングに頼れないこと
になり、様々なAndroid/iOSデバイス向けのス
ケーリングのコードを自前実装することになり、
かなり手間になった
失敗点: 自前スケーリングは面倒
- 54. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
54
• ここまでの手間を経て、ようやくCocos2d-x組み
込みは実用に耐える技術として確立する
• しかし、Cocos2d-x自体も日々変化しており、明
日はまた異なるものになっているかもしれない
• Director::getInstance()-
>getRunningScene()->getChildren().at(0)だ
とCameraが取れてしまう(現在のシーンはat(1))
• Cocos2d-xのSceneは、Node/Layerと異なり、
Camera、BaseLight、NavMesh、
Physics3DWorldを持つ
• Cocos2d-xは3D/VRゲームエンジンへと変容
を遂げつつある(Cocos2d-xからCocosへ)
これからのCocos2d-x
- 55. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
55
• Cocos Studio開発終了
• Cocos Creatorが主流に
• Electronベースでオープンソース。Unityライ
クなビジュアル開発環境
• Chukongは、コンソール版をキャンセルして
でも開発環境の充実を第一目標に置いている
• (UnityがC#で開発するように)JavaScriptでの
ダイナミックな開発を推奨、C++は重い処理
を書く場合以外は使われなくなる
• プロジェクト構成が従来と変わるので、新し
くCocosプロジェクトを起こすならCocos
Creatorベースとすべし
これからのCocos2d-x
- 56. Copyright © GREE, Inc. All Rights Reserved.
Cocos2d-x組み込みによるクライアント統合
56
• 余計な血は流さない
• Cocos2d-xへのパッチは最小限に
• Cocos2d-x最新版への追随更新を妨
げない
• ゴールはあくまでアプリを活かすこと
• UnityにCocos2d-xを組み込むことも
不可能ではない… かもしれない
• ゲームエンジンの深層は学びの宝庫で
ある
総括: 外科手術の心得