馴れ初め
個人ゲームのデータをFirebaseのFireStoreにFunctions経由で保存しようとした
開発段階だからとemulatorをセッティングし、Unityからアクセスしようとした
つまづき
sdkのemulatorの対応状況がバラバラ
emulatorの設定メソッドくらい用意してください・・・
状況
Firebaseのemnulatorをセットアップし、Unityのsdkを入手した。
さて、emulatorに繋ごうとしてドキュメントを見ると
FireStore ⇨ settingsでemulatorに接続するように設定できる(ちょっとトリッキー)
Functions ⇨useFunctionEmulator というメソッドが用意されている(ちゃんとしてる)
authentication ⇨ねーよ
Google?
こまるポイントその1
authがGoogle鯖に繋ぎにいくので、
auth.CreateUserWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
とすると、普通にGoogleサーバにauthのユーザーが作られます。
(簡単すぎてびびるくらい)
そう、emulatorにはユーザーが作られない(当たり前)
でも、開発中はローカルのemulatorでやりたいわけです
色々試行錯誤するも、結局、emulatorコンソールまたは、functionsでメソッド書いてできた
こまるポイントその2
非同期処理が色々面倒ですが、Functionsもauthもsdkの使い方は簡単で
認証処理をして(省略)、サーバ接続のコードを書く(省略)と、接続時に認証情報を渡してくれるようです
(認証情報を自分で渡す必要がないらしい)
auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
}
//hogehoge
await functions.GetHttpsCallable("helloWorld")
.CallAsync(hogeData)
.ContinueWith(task => {
// HogeHoge
}
);
こうすることで、サーバ側にはcontextにauthとして情報が渡ります
多分、一般的にはサーバ側ではユーザーが認証されてる(auth情報を使う)かどうかを確かめて処理を動かすので
exports.helloWorld = functions.https.onCall((data, context) => {
if (context.auth === undefined || !context.auth.uid || context.auth.uid === 0) {
throw new functions.https.HttpsError('unauthenticated');
}
return admin.auth().getUser(userId)
.then(() => {
// HogeHoge
}};
ととなるかと思います。これは、Google鯖上では普通に動きます。
が、emulator上ではgetUser で例外がスローされます。ユーザーないので・・・
とりあえずの回避法
ローカルでの開発中はgetUserをすっ飛ばす
は、流石に強引すぎるので。
1)auth emulatorに authと同じユーザーIDでユーザーを作る
2)クライアントでは、auth認証で得られたuserIdをなんらかの方法でFunctionsに渡す
(今回は普通にデータに突っ込んだ)
3)Functions側ではemulatorで動いているかをチェックして、emulatorの場合は、
context.auth.uidの代わりに、送られてきたユーザーIDを使う
という回避方法を使ってみた
var userId = context.auth.uid;
if (process.env.FUNCTIONS_EMULATOR === 'true') {
userId = data.userId;
}
return admin.auth().getUser(userId)
// HogeHogeな処理
結論
そもそもこれで正しいのかググってもあまり出てこない。が、開発中部分なんで良いんでは、という気がしている
(個人ゲームだし!)
困ってる人があまりいない、ということは、UnityでFirebaseを使う際にAuthentication使ってないのかなぁ
お願い
正しい(と思われる)方法があったら教えてください。
あとGoogleの人はさっさとUnitySDKにuseEmulatorを実装してください。
FireStoreも正式なメソッドではなく、Settingsメソッドでなんとかしてますよねぇ
蛇足
ちなみに、
func useEmulator(withHost host: String, port: Int)
FirebaseAuth.useEmulator(withHost host: String, port: Int)
とネイティブ版にはあるので、ネイティブプラグインを使えばできそうですが、
このためにそこまでやる?
って感じなのでやめました
なお、Functions自身はonCallを使うととっても簡単にサーバとやり取りできます
UnityのWebRequestでJSONでうんたらこうたらするより随分簡単でした
(どのみち非同期処理はいるんだけど・・・)