UnityでGoogle Sign Inを実装する場合、Google公式のライブラリを利用するのが一般的です。
しかし、最終更新日が5年ぐらい前で、最新のFirebaseライブラリーと組み合わせて使うと動きません。
また公式ライブラリは内部でWebViewを使っていますが、現在はWebViewの代わりにWKWebViewを使わないとAppleの審査が通らないので実質使えません。
この問題を解消するため、iOSネイティブ連携でGoogle Sign Inを行う方法と、Sign Inした結果をUnity用のFirebaseAuthライブラリーと連携させる方法を詳しく解説します。
Androidネイティブ連携でのGoogle Sign Inを行う方法はコチラ

Firebaseの用意
Firebaseにアプリ用のプロジェクトを作成したらUnityアプリとして登録し、iOSの欄に必要項目を記入します。
そして、Unity側で呼ぶFirebaseAuthとiOSネイティブのGoogle Sign Inを紐付けるための準備をしていきます。
Google Sign Inの有効化
構築欄のAuthenticationを選び、新しいプロバイダを追加からGoogleを選び、Google Sign Inを有効にします。

設定ファイルの配置
全ての準備が完了したら、左上の歯車ボタンを押して、プロジェクトの設定を選び、googleServices-info.plistをダウンロードしたら、UnityプロジェクトのAssetsフォルダに配置します。

iOSネイティブでGoogle Sign In
では、iOSネイティブのGoogle Sign Inを実装していきましょう。
まず、File > Build Settingsで、PlatformをiOSに切り替えておきます。
Google Sign Inライブラリーの追加
コードを実装していく前に、エラーがでないようGoogle Sign Inライブラリーを最初に追加しておきます。
iOSフォルダ内にあるPodfileを開き、target ‘UnityFramework’ do から end の間に次の1行を追加します。
pod 'GoogleSignIn'
追加したら、ターミナルを開き、iOSフォルダ直下に移動して「pod update」コマンドを実行します。
MyUnityAppControllerの実装
最新のiOSアプリではちょっと違うのですが、ちょっと前まで、iOSネイティブはUIApplicationDelegateプロトコル(インタフェース)を実装したAppDelegateというクラスがアプリ起動の起点になっていました。
Unityの場合はUIApplicationDelegateプロトコルを実装した「UnityAppController.mm」がアプリの起動と同時に呼び出されます。
(iOS/Classesの中にあります)
このUnityAppControllerを継承したMyUnityAppControllerに起動クラスを差し替え、そこにGoogle Sign Inを実装することでUnityでのGoogle Sign Inを実現していきます。
という訳で早速実装していきましょう。
UnityでiOSビルドをすると作られるiOSワークスペースをXCodeで開いたら
File > New > File…
で「Cocoa Touch Class」を選び
Classに、MyUnityAppController
Subclass ofに、UnityAppController
Languageは、Objective-C
とします。
保存先は、Assets/Plugins/iOS
Targetsは、Unity-iPhoneを外し、UnityFrameworkに変えてください。
こっちにしないとコードヒントがでなくてコーディングしにくいです。
実装内容は以下の通り。
コードの詳細は全部コメントに書いたのでそちらを参照してください。
コードはObjective-Cで書いてください。Swiftで書く方法もありますがまどろっこしいので。
#import "Prefix.pch"
#import "MyUnityAppController.h"
#import "GoogleSignIn.h"
@implementation MyUnityAppController
+ (void)googleSignIn {
UnityAppController *appDelegate = (UnityAppController *)[UIApplication sharedApplication].delegate;
UIViewController *currentViewController = appDelegate.window.rootViewController;
if (currentViewController) {
[GIDSignIn.sharedInstance
signInWithPresentingViewController:currentViewController
completion:^(GIDSignInResult * _Nullable signInResult, NSError * _Nullable error)
{
if (error) {
// Unity側のTestController.GetIDTokenFailedメソッドを呼び出す。
// 第一引数はクラス名、第二引数は関数名、第三引数は関数の引数
UnitySendMessage([@"TestController" UTF8String], [@"GetIDTokenFailed" UTF8String], [[NSString stringWithFormat:@"%ld", error.code] UTF8String]);
} else {
if (signInResult.user.idToken != nil) {
// Unity側のTestController.GetIDTokenメソッドを呼び出す。
// 第一引数はクラス名、第二引数は関数名、第三引数は関数の引数
UnitySendMessage([@"TestController" UTF8String], [@"GetIDToken" UTF8String], [signInResult.user.idToken.tokenString UTF8String]);
} else {
// Unity側のTestController.GetIDTokenFailedメソッドを呼び出す。
// 第一引数はクラス名、第二引数は関数名、第三引数は関数の引数
UnitySendMessage([@"TestController" UTF8String], [@"GetIDTokenFailed" UTF8String], [@"" UTF8String]);
}
}
}];
} else {
NSLog(@"ViewControllerを取得できませんでした。");
}
}
#ifdef __cplusplus
extern "C" {
#endif
// Unity側から呼び出すメソッド
void googleSignIn() {
[MyUnityAppController googleSignIn];
}
#ifdef __cplusplus
}
#endif
// GoogleSignInの結果をハンドリングする
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
BOOL superResult = [super application:app openURL:url options:options];
BOOL handled = [GIDSignIn.sharedInstance handleURL:url];
if (handled) {
return YES;
}
return superResult;
}
@end
起動クラスの差し替え
デフォルトでは、UnityAppControllerが呼び出されるようになっているので、そこを先程作ったMyUnityAppControllerが呼び出されるよう、Classes/mainファイルを書き換えます。
AppControllerClassNameにセットされている文字列のところ。
#include "RegisterFeatures.h"
#include <csignal>
#include "UnityInterface.h"
#include "../UnityFramework/UnityFramework.h"
void UnityInitTrampoline();
// WARNING: this MUST be c decl (NSString ctor will be called after +load, so we cant really change its value)
// 差し替える
const char* AppControllerClassName = "MyUnityAppController";
//const char* AppControllerClassName = "UnityAppController";
info.plistの修正
次に、OAuth2でGoogle Sign InするためのクライアントID情報をInfo.plist (XCode上では拡張子無しのInfoと表示されています)に追加します。
XCodeでInfoファイルを右クリックしてOpen As > Source Code
でInfo.plistの内容が表示されたら、次の項目を追加します。
YOUR_IOS_CLIENT_IDの欄には、FirebaseからダウンロードしたGoogleService-Info.plist内にある「CLIENT_ID」の値を、YOUR_DOT_REVERSED_IOS_CLIENT_IDの欄には、GoogleService-Info.plist内にある「REVERSED_CLIENT_ID」の値を記入します。
<key>GIDClientID</key>
<string>YOUR_IOS_CLIENT_ID</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>YOUR_DOT_REVERSED_IOS_CLIENT_ID</string>
</array>
</dict>
</array>
仕上げ (必ずやらないとダメ)
最後に、全ての実装が完了したら必ずMyUnitAppControllerのヘッダーと本体のTarget Membershipを外してください。
Assets/Plugins/iOSに配置したファイルはiOSビルドすると自動的にコピーがiOSプロジェクト内にマージされるため、Targetのチェックを入れたままだとファイルが2重になってduplicateエラーが起こります。
その後Unity側でiOSビルドを実行します。
iOSビルドを実行することで先程作ったAssets/Plugins/iOS/MyUnityAppControllerファイルがiOSプロジェクト内にコピーされて組み込まれるので、必ず忘れないようにしてください。
以上でiOSネイティブ側の実装は完了です。
試しに実機でiOSビルドを試して見てください。
問題なく起動するはずです。
Unity用FirebaseAuthと連携
次に、Unity側にFirebaseAuthパッケージを導入して、iOSネイティブで成功したGoogle Sign Inの結果をFirebase Authに紐付ける処理を実装していきます。
FirebaseAuthパッケージの導入
以下のリンクから最新版のFirebase Unity SDKをダウンロードします。
今回は、2023/7/20時点で最新のバージョン11.2.0を導入します。
既に他のFirebaseパッケージを導入済の場合は同じバージョンのFirebaseAuthパッケージを入れるか、最新のパッケージを全て入れ直してください。
そうしないとエラーで動きません。
ダウンロードしたら解凍して、FirebaseAuth.unitypackage をimportします。
C#の実装
iOSネイティブのMyUnityAppControllerで、UnityのTestControllerのメソッドを呼び出すよう実装していたので、クラス名はTestControllerとします。
TestControllerに定義したSignInWithGoogleメソッドをButtonなどに当てて呼び出すと、iOS側のGoogle Sign Inが実行され、結果がUnity側のメソッドを通して返ってきます。
詳細はコードのコメントを参照してください。
using UnityEngine;
using Firebase.Auth;
using Firebase.Extensions;
using System.Runtime.InteropServices;
public class TestController : MonoBehaviour
{
private FirebaseAuth auth;
Firebase.DependencyStatus dependencyStatus = Firebase.DependencyStatus.UnavailableOther;
private void Start()
{
// FirebaseAuthの初期化
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available)
{
auth = FirebaseAuth.DefaultInstance;
}
else
{
Debug.Log($"error: {dependencyStatus}");
}
});
}
[DllImport("__Internal", EntryPoint = "googleSignIn")]
static extern void googleSignIn();
// ネイティブに定義してあるメソッドを呼ぶ
public void SignInWithGoogle()
{
#if UNITY_IOS
// iOSネイティブのメソッドを呼ぶ
googleSignIn();
#elif UNITY_ANDROID
// Androidネイティブのログインはこっちに
#else
Debug.Log($"SignInWithGoogle error: unknown platform");
#endif
}
// ネイティブから呼び出される。Google Sign Inで取得したIDTokenを受け取る
public void GetIDToken(string idToken)
{
Credential credencial = GoogleAuthProvider.GetCredential(idToken, null);
// GoogleアカウントをAuthに紐付ける
auth.SignInWithCredentialAsync(credencial).ContinueWith(authTask =>
{
if (authTask.IsCanceled)
{
Debug.Log($"LinkWithCredentialAsync Cancelled");
}
else if (authTask.IsFaulted)
{
Debug.Log($"LinkWithCredentialAsync Faulted");
}
else
{
Debug.Log($"LinkWithCredentialAsync Complete!");
}
});
}
// ネイティブから呼び出される。Google Sign Inに失敗した事を教えてもらう
public void GetIDTokenFailed(string errorCode)
{
Debug.Log($"GetIDToken Failed!! {errorCode}");
}
}
うまく処理が完了すると、FirebaseAuthとの連携が完了し、FirebaseのAuthenticationにGoogle Sign Inしたユーザーの情報が登録されます。
