【Unity】Firebaseを使用するための手順

はじめに

こんにちは、SHOJIです。

本記事ではUnityとFirebaseを連携するときの設定についてまとめます。

Unity Editorのバージョン

前提として、Unity Editorは「2021.3.1f1」を使用しています。 Unity EditorとFirebase Unity SDKにはバージョンによる相性があるようで、以前にはこのようなことがありました。

deadline-driven-developer.hatenablog.com

この記事を参考にされる場合は、一旦バージョンを合わせて動くことを確認してからバージョンを上げて頂くのが、手間ですが間違いないかと思います。

Firebase Unity SDK のインポート

  1. ここから任意のバージョンのFirebase Unity SDKをダウンロードします。github.com

  2. ダウンロードしたFirebase Unity SDKを展開します。

  3. Unity Editorを開き、「Assets」-「Import Package」-「Custom Package...」から「2」で展開したFirebase Unity SDK内のunitypackageをインポートします。「dotnet3」と「dotnet4」でフォルダが分かれていますが、Unity 2019以降は「dotnet4」の方のパッケージをインポートします。firebase.google.com

  4. どのパッケージをインポートするかは使用する機能次第ですが、僕は以下の4つは入れておいて損はないので必ずインポートし、

    • FirebaseAuth.unitypackage
    • FirebaseAnalytics.unitypackage
    • FirebaseCrashlytics.unitypackage
    • FirebaseMessaging.unitypackage

    加えてデータベース機能も必要な場合はこちらをインポートします。

    • FirebaseDatabase.unitypackage

Firebaseの設定

  1. ブラウザでFirebaseコンソールにアクセスし、新規にプロジェクトを作成します。
  2. Firebaseの「プロジェクト設定」-「パッケージ名」と、Unityの「Project Settings」-「Package Name」は同じにします。
  3. AnalyticsとCrashlyticsはデフォルトで有効になっているのでそのままに。AuthenticationとRealtime Databaseはデフォルトでは有効になっていないため、必要な場合は手動で有効にします。

  4. 機能を有効にしたら「2」の「プロジェクト設定」から google-services.json をダウンロードして、UnityのAssetsフォルダ配下に格納します。

  5. UnityでFirebaseを使用するためのコードを書きます。

    private static Firebase.FirebaseApp firebaseApp;
    private static FirebaseAuth firebaseAuth; // Authenticationを使う場合

    public async Task PrepareFirebase() { try { if (firebaseApp != null) { return true; }

        var dependencyStatus = await Firebase.FirebaseApp.CheckAndFixDependenciesAsync();
    
        if (dependencyStatus == Firebase.DependencyStatus.Available)
        {
            // DefaultInstanceの生成時に副作用として初期化が行われるため、これらのコードを削除してはいけない
            firebaseApp = Firebase.FirebaseApp.DefaultInstance;
            firebaseAuth = FirebaseAuth.DefaultInstance; // Authenticationを使う場合
            Debug.Log($"Firebase fixed dependencies successfully.");
            return true;
        }
        else
        {
            Debug.LogError(String.Format("Could not resolve all Firebase dependencies: {0}", dependencyStatus));
            return false;
        }
    }
    catch (Exception exception)
    {
        Debug.Log(exception.Message);
        return false;
    }
    

    }

    Firebaseの初期化処理はアプリ起動時に一度だけ行えばよいのですが、このメソッドは複数回呼ばれる想定で作っています。これには理由がありまして、Unityで開発する場合、シーンごとにUnity Editorでデバッグすることが多く、シーンごとにFirebaseの初期化処理を行えるようにした方がデバッグがしやすいためです。とはいえ、シーンをまたぐたびに無駄な初期化処理を走らせたくないので、メソッドの冒頭で初期化されているかのチェックを行うようにしています。

Authenticationの設定(匿名認証とGoogle認証のみ記載)

匿名認証

  1. ブラウザでFirebaseコンソールにアクセスし、匿名認証を有効にします。

  2. Unityで匿名認証のためのコードを書きます。

    public static string UserId { private set; get; } = string.Empty;

    public async Task SignInAnonymously() { try { var firebaseUser = await firebaseAuth.SignInAnonymouslyAsync(); UserId = firebaseUser.UserId; return firebaseUser; } catch (Exception exception) { Debug.Log(exception.Message); return null; } }

    僕は同期的に処理したいケースが多いため、awaitして同期的に処理させています。公式のサンプルではContinueWithを繋げて非同期的に処理しています。

Google認証

  1. ブラウザでFirebaseコンソールにアクセスし、匿名認証を有効にします。
  2. Unityでapkファイルをビルドします。
  3. "C:\Program Files\Java\jdk-18.0.2\bin\keytool.exe" -printcert -jarfile [filename].apkコマンドからビルドしたアプリのSHA1証明書を取り出します。 ※Windowsを使用している場合、keytool.exeのパスが通っていないのでJavaフォルダから探してください。
  4. 実行結果のSHA1の値をコピーして、Firebaseの「プロジェクトの設定」-「フィンガープリントを追加」から貼り付けます。
  5. Unityでgoogle-signin-plugin-1.0.4.unitypackageをインポートします。github.com
  6. Google認証のためのコードを書きます。

    public static string UserId { private set; get; } = string.Empty;
    
    public async Task SignInGoogleSilently()
    {
        try
        {
            StartWithSignInGoogle();
            var signIn = await GoogleSignIn.DefaultInstance.SignInSilently();
            var credential = GoogleAuthProvider.GetCredential(signIn.IdToken, null);
            var firebaseUser = await firebaseAuth.SignInWithCredentialAsync(credential);
            UserId = firebaseUser.UserId;
            return firebaseUser;
        }
        catch (Exception exception)
        {
            Debug.Log(exception.Message);
            return await SignInGoogle();
        }
    }
    
    public async Task SignInGoogle()
    {
        try
        {
            StartWithSignInGoogle();
            var signIn = await GoogleSignIn.DefaultInstance.SignIn();
            var credential = GoogleAuthProvider.GetCredential(signIn.IdToken, null);
            var firebaseUser = await firebaseAuth.SignInWithCredentialAsync(credential);
            UserId = firebaseUser.UserId;
            return firebaseUser;
        }
        catch (Exception exception)
        {
            Debug.Log(exception.Message);
            return null;
        }
    }
    
    private void StartWithSignInGoogle()
    {
        if (GoogleSignIn.Configuration == null)
        {
            // Google SignInの設定
            GoogleSignIn.Configuration = new GoogleSignInConfiguration
            {
                RequestIdToken = true,
                // Copy this value from the google-service.json file.
                // oauth_client with type == 3
                WebClientId = "********-***************************.apps.googleusercontent.com"
            };
        }
    }
    

    SignInGoogleSilentlyはサインインの状態を確認して自動でサインインを試みます。 SignInGoogleはGoogleアカウントの候補を表示してパスワードの入力を求めます。

    なお、SignInGoogleSilentlyは自動サインインに失敗した場合はSignInGoogleを呼ぶようにしているため、毎回サインインし直させる事情がない限りはSignInGoogleSilentlyだけあれば事足りるかと思います。

    StartWithSignInGoogleは認証処理の初期設定を行うのですが、Web Client Idに値を設定する必要があります。 こちらはFirebaseの「Authentication」-「ログインプロバイダ」-「Google」-「ウェブSDK構成」-「ウェブ クライアント ID」の値を設定してください。

Realtime Databaseの設定

  1. ブラウザでFirebaseコンソールにアクセスし、Realtime Databaseを有効にします。 あとで設定を変更できるため、最初はテストモードで構いません。

  2. Unityで更新用のコードを書き、更新できることを確認します。

    public void InsertData(string referenceKey, string key, T data)
    {
        var databaseReference = firebaseDatabase.RootReference;
        var json = JsonUtility.ToJson(data);
        databaseReference.Child(referenceKey).Child(key).SetRawJsonValueAsync(json);
    }

    public class Test { public int value = 0;

    public Test(int value)
    {
        this.value = value;
    }
    

    }

    InsertDataのようなメソッドを作ればTestクラスのようなインスタンスを渡すことでデータを登録できます。 referenceKeyはFirebaseにサインインしたときに得られるユーザID、keyは何でも構いません。

  3. Unity側で更新処理を実行したらFirebaseコンソールに戻り、データが登録されていることを確認します。

  4. Firebaseにデータが登録されていたらRealtime Databaseのルールを変更します。 「1」で設定したテストモードは、Realtime Databaseのルールに制限をかけないことを指しており、ここで行うルール変更によってテストモードは終了することになります。(日本語が分かりにくいのですが、Realtime Databaseに本番モード・テストモードが存在するわけではなく、参照・更新のルールがない状態を便宜上テストモードと呼んでいる、ということです) こちらはルールのサンプルです。ルールはデータの構造と合わせる必要があります。 ここでは「2」のInsertDataで更新した場合を想定しています。referenceKeyにユーザIDを設定しているので、構造としてはデータベースの直下にユーザIDが並び、その下にkeyで指定した名称のデータが並びます。

    上記のルールでは「$userId」のデータの読み書きはauth.uidと$userIdが同一の場合のみ行えるとしています。したがって、サインインしているユーザ自身のデータしか見えず触れません。

  5. ルールを変更したら、ユーザ自身のデータ以外は触れないことをUnityでテストコードを書いて試験してください。 試験のコードはここでは割愛させて頂きます。

Release版のアプリのSHA1証明書のフィンガープリント

ここからはGoogle Play Consoleにアプリを登録してからの話になります。 「Google認証」の説明の中で、APKファイルからSHA1証明書を抜き出してFirebaseの「プロジェクトの設定」-「フィンガープリントを追加」に貼り付ける手順がありました。

Unityから端末に直接インストールして動作させる場合はこれでよいのですが、Google Playを経由する場合はGoogle Play Consoleで付与しているSHA1証明書をFirebaseに登録する必要があります。

  1. Google play consoleでアプリをリリースします。内部テストやクローズドテストで問題ありません。
  2. 「設定」-「アプリの完全性」-「アプリの署名」を開き、SHA1証明書をコピーして、Firebaseの「プロジェクトの設定」-「フィンガープリントを追加」に貼り付けます。

おわりに

UnityでFirebaseを使用するための基本設定については以上です。

本当はFirebaseAnalyticsを使ってイベント情報を収集する手順も書きたかったのですが、長くなってしまったので今回は見送ります。FirebaseAnalyticsはあまり落とし穴がないので、別途検索して頂ければ容易に実装できるかと思います。