[GPGS] cocos2dx/AndroidでGoogle Play Game Services C++ SDKを使おうと思ってハマった

 みなさまおひさしぶりです。ここのところ曲作ったり世界樹の防衛をしていたりと多忙だったんですが、そのへんのタスクが掃けたのでこのGWは久しぶりに練習ゲーム開発をやってました(1割くらい)。練習なのでとりあえず色々組み込んでみているんですが、今回はcocos2dx(主にAndroid)でGoogle Play Game Servicesを導入しときにそこそこハマったのでその部分をメモしておきます。

Google Play Game Services

 Google Play Game Services(以下GPGS)は、Google先生がやっているソーシャル機能とかマルチプレイとかその辺のサービスの総称です。iOSでいうところのGame Centerですが、Game Centerとは異なりAndroid以外にもiOSやWebからも利用することが出来ます(ただiOSで利用しているアプリを見かけたことがないような)。プラットフォーム固有のSDKもありますが、C++から利用できるSDKもあるため、両プラットフォーム対応も簡単にできます。

iOSでの実装

 こちらは特にハマることなくすんなり実装できました。必要なSDK(C++のものとiOSのもの全部)を落としてきて.frameworkや.bundleをプロジェクトに追加、あとはサンプルコードの通りに記述すると動きます。プロジェクトに追加すべきファイルは

https://developers.google.com/games/services/cpp/gettingStartedIOS

に記載されています。追加するファイルがiOS版SDKと若干異なるので注意が必要です。間違えると動きますがアセット類の読み込みに失敗します。

Androidでの実装

 ハマりました。以下のgithubリポジトリがAndroid(iOSも)での実装例なので、こちらを参考にするとうまくいくのですが、Androidの場合logcatで流れるエラーの量が多いためエラーメッセージに気づかず原因特定にだいぶ時間がかかりました。

https://github.com/fusijie/GooglePlayGameServices

 気をつけたいのは以下の点です。

  • gpg::GameServices::Builder::Createがnullを返す
  • AndroidPlatformConfiguration::Validがfalseを返す

 この2つ、原因は同じで、AndroidPlatformConfiguration::SetActiviryを呼ぶ前にgpg::AndroidInitialization::JNI_OnLoadを呼び出さないと、SetActivityの呼び出しが無視されます。SetActivityの呼び出しに失敗するとValidがfalseを返すため、Createの呼び出しにも失敗します。

Attempting to call SetActivity prior to AndroidInitialization: ignoring.

のようなエラーが発生している場合は、gpg::AndroidInitialization::JNI_OnLoadの前にAndroidPlatformConfiguration::SetActivityが呼び出されています。したがって、GPGSを組み込む場合はゲームプロジェクトのJava&JNIコードの他に、cocos2dx側のコードを弄る必要があります。面倒ですね。

cocos2dx側に変更を加える

 以下の手順は、cocos2dx 3.0で行った際の手順です。その他のバージョンでは場所が異なる場合があります。

 面倒ですが変更点はそこまで多くありません。まず、cocos2dx側のAndroid.mkを修正します。場所は「cocos2d/cocos/2d/platform/android」です。

LOCAL_C_INCLUDES := $(LOCAL_PATH) \
                    $(LOCAL_PATH)/../.. \
                    $(LOCAL_PATH)/../../.. \
                    $(LOCAL_PATH)/../../../base \
                    $(LOCAL_PATH)/../../../math/kazmath \
                    $(LOCAL_PATH)/path/to/gpgs # この行を追加

「path/to/gpgs」の部分は自分の環境に合わせて変更してください。次に、同じ階層にある「javaactivity.cpp」を編集します。

#include "gpg/android_initialization.h"
// ↑これをインクルード

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    JniHelper::setJavaVM(vm);
    gpg::AndroidInitialization::JNI_OnLoad(vm); // この行を追加
    return JNI_VERSION_1_4;
}

 これでcocos2dx側の修正は完了です。あとはGoogle先生公式ドキュメントにしたがって実装すれば動きます。

もうちょっと注意したい点

 上記が一番のハマリポイントかと思います(ちゃんとドキュメント読めば書いてあるんですけどね...)。それ以外にもハマりそうなポイントを以下に纏めておきます。

Android 4.0系以降でGPGSを使う場合

 Android 4.0系以降をサポートする場合は、アクティビティが「onActivityResult」をオーバーライドし、C++側にその結果を転送してやる必要があります。

private static native void nativeOnActivityResult(
    Activity activity, int requestCode, int resultCode, Intent data
);

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    nativeOnActivityResult(this, requestCode, resultCode, data);
}
#include <gpg/android_support.h>

extern "C"
{
    JNIEXPORT void Java_com_example_Hoge_nativeOnActivityResult(
        JNIEnv *env, jobject thiz, jobject activity, jint requestCode,
        jint resultCode, jobject data
    )
    {
        // ↓これを呼ぶ
        gpg::AndroidSupport::OnActivityResult(
            env, activity, requestCode,
            resultCode, data
        );
    }
}

 上記のコードが必須です。

Android 2.3系でGPGSを使う場合

 Android 2.3系をサポートする場合は、上記のonActivityResultに加え、アクティビティの状態変化系のイベントを全てオーバーライドし、C++側にその結果を転送してやる必要があります。長いのでコードは割愛しますが、先ほど挙げた参考リポジトリに実装が記述されていますので、そちらを参考に実装してください。

参考: https://github.com/fusijie/GooglePlayGameServices/blob/master/proj.android/jni/hellocpp/main.cpp

サインイン出来ない

 うまく実装できたにもかかわらずサインインに失敗する場合は、デバッグ用の署名でリザインしていないか確認して下さい。ログインのテストを行うには、Google Developer Consoleで登録したSHA1に対応する署名でリザインする必要がありますので、リリースビルドを行なってください。

まとめ

 ちゃんとドキュメントとエラーメッセージを読めばそんなにハマらない!

0 件のコメント :

コメントを投稿