この記事に導入までは書いてるのでその続きです。
Firebaseコンソールでの作業
左カラムのDatabaseからRealtimeDatabaseを選択して新規に一つ作成します。
データベースの画面でルールタブを開き、以下のように記述します。
{ "rules": { ".read": "auth.uid !== null", "ranking":{ "$user_id": { ".read": "auth.uid !== null", ".write": "auth.uid !== null && $user_id === auth.uid", "coin":{".validate": "newData.isNumber()"}, "name":{".validate": "newData.isString()"} } } } }
rulesという項目に設定全体が収まるように書きます。
.readという項目は読み込みに関する権限設定です。”auth.uid !== null”は認証済みのユーザのみが読み込みできる事を指します。
ranking子要素はデータタブで表示されるツリーのルートの直下にある子に設定した名前です。実際にはこのパス以下にデータを入れていきます(私のアプリではランキングに利用したのでこの様な名前にしただけで、自由に設定できます)。(この設計の場合、実装時に必要となるreference layerは”ranking”になります)
“$user_id”というのはユーザの識別に使うIDが子要素としてrankingの直下に来ることを指します。rankingとは異なり、$が付いた予約済みの特別な変数を指します。
それ以下の.readでは同様に認証済みユーザのみ、.writeでは認証済みでなおかつユーザIDが認証IDと一致するデータのみ上書きできる事を指します(一致するものが無い場合は追加可能)。
その下のcoinやnameというのはアプリでランキングに使用するコイン枚数やユーザ名がユーザIDの子要素として存在する事を意味しており、それぞれの直下に”.validate”といのがあるのは、数字や文字列以外のデータを拒否する設定を意味します。
ルールタブの右側にシミュレータというのがありますので、実装前に読み込みと書き込みのテストを行います。どの部分で弾かれたか、どの部分が通ったかというのを赤い×と緑のチェックで表示してくれますので、おかしな部分があれば修正します。RealtimeDatabaseのルールの仕様として、指定したパスまでの全ての階層の権限がパスされないとアクセス拒否されるので設計に注意が必要です。
Unity側の実装
void StartListener() { //rankingからscoreという子要素のサイズの昇順に並べて最後から5000番目まで取得(降順は無いのでこうやって取得して並び替える) FirebaseDatabase.DefaultInstance.GetReference("ranking").OrderByChild(score_col).LimitToLast(5000) .ValueChanged += (object sender2, ValueChangedEventArgs e2) => { if (e2.DatabaseError != null) { Debug.LogError(e2.DatabaseError.Message); return; } if (e2.Snapshot != null && e2.Snapshot.ChildrenCount > 0) { //表示をクリア foreach (var childSnapshot in e2.Snapshot.Children) { Debug.Log(childSnapshot.GetRawJsonValue()); if (childSnapshot.Child(score_col) == null || childSnapshot.Child(score_col).Value == null) { Debug.LogError("Bad data in sample. Did you forget to call SetEditorDatabaseUrl with your project id?"); break; } else { //データを逆順にデータリストに追加する処理 } } //ランキングの表示処理 } }; } void InitializeFirebase() { FirebaseApp app = FirebaseApp.DefaultInstance; // NOTE: You'll need to replace this url with your Firebase App's database // path in order for the database connection to work correctly in editor. //DBアクセス前に必要 FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://***.firebaseio.com/"); if (app.Options.DatabaseUrl != null) app.SetEditorDatabaseUrl(app.Options.DatabaseUrl); StartListener(); isFirebaseInitialized = true; } void FirebaseSDKUpdate() { Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => { var dependencyStatus = task.Result; if (dependencyStatus == Firebase.DependencyStatus.Available) { // Create and hold a reference to your FirebaseApp, // where app is a Firebase.FirebaseApp property of your application class. // app = Firebase.FirebaseApp.DefaultInstance; //var app = Firebase.FirebaseApp.DefaultInstance; // Set a flag here to indicate whether Firebase is ready to use by your app. AnonymousLogin(); } else { UnityEngine.Debug.LogError(System.String.Format( "Could not resolve all Firebase dependencies: {0}", dependencyStatus)); // Firebase Unity SDK is not safe to use here. } }); } void AnonymousLogin() { var auth = FirebaseAuth.DefaultInstance; auth.SignInAnonymouslyAsync().ContinueWith(task => { if (task.IsCanceled) { Debug.LogError("SignInAnonymouslyAsync was canceled."); return; } if (task.IsFaulted) { Debug.LogError("SignInAnonymouslyAsync encountered an error: " + task.Exception); return; } var newUser = task.Result; Debug.LogFormat("User signed in successfully: {0} ({1})", newUser.DisplayName, newUser.UserId); InitializeFirebase(); }); } void Start() { FirebaseSDKUpdate(); //表示部の初期化処理 }
こんな感じに書いていきます。新しくデータが投稿されるとリロード無しで即座にアプリ側でも反映されます。
参考:
https://medium.com/teamarimac/how-to-develop-a-complete-leader-board-for-a-unity-game-using-firebase-facebook-sign-in-google-d865f577b303
http://www.project-unknown.jp/entry/firebase-login-vol3_1#OrderByChild
コメント