初めてのFirebase × Unity ~ Firestoreのデータ取得偏 ~

## 目次
- [本稿執筆の背景](#本稿執筆の背景)
- [対象読者](#対象読者)
- [本稿の対応範囲](#本稿の対応範囲)
- [Step1: Firebaseにアプリの登録 ～ 既存Unity Projectへの導入](#step1-firebaseにアプリの登録--既存unity-projectへの導入)
- [Step2: FirebaseコンソールからFireStore Databaseの作成](#step2-firebaseコンソールからfirestore-databaseの作成)
- [Step3: Unity Project から FireStoreのデータの読み取り](#step3-unity-project-から-firestoreのデータの読み取り)
- [完成形](#完成形)

## 本稿執筆の背景
- 個人でUnityを用いてオンラインゲームをなるべく無料で作りたかった
    - サーバー側の実装にあまり苦戦しなさそうで、無料枠で利用できる範囲が豊富だった
    - 一度もFirebaseを使用したことがなかったため、利用したいと思った
    - P2Pでの通信処理はNAT系の処理に時間がかかりそうで、ゲーム制作の熱が冷めかねないと思ったため、Client-Server方式で利用できるパターンを探していた。


### 今回では利用しないほかのオンラインゲーム用のサーバー検討候補

- Azure Playfab
     - 無料枠ではリアルタイム性がFirestoreのほうが優れている
- Epic Online Service(EOS)
     - EOSでは対戦用のマッチングはできそうだが、セーブデータを何かしらのData Storeに保持する手間が必要なため
- Steamworks
    - EOSと同様の理由 ＋ 利用料金の懸念のため
 - AWS
    - 手間がFirebaseよりもかかりそうなため
    - 今回作成したいゲームの規模は比較的小さい？ため、Firebaseの無料枠で十分だったため
- Photon
    - 金額の懸念により断念

## 対象読者
- Unity×Firebaseでオンラインゲームを作りたい人、または利用してみたいと思ってるけど、公式を流し見しただけではあまり理解できなかった人
- iOSやAndroid向けのUnityプロジェクトとFirebaseの連携方法ではなく、**PC向けのUnityプロジェクトとFirebaseの連携方法を知りたかった人**

↑  つまり**全世界線の私**

## 本稿の対応範囲
1. Firebaseコンソールからアプリの登録 ～ 既存Unity Projectへの導入
1. FirebaseコンソールからFireStore Databaseの作成
1. Unity Project から FireStoreのデータの読み取り

## Step1: Firebaseにアプリの登録 ～ 既存Unity Projectへの導入
- [Firebaseコンソール](https://console.firebase.google.com/?hl=ja)にログインし`Firebase プロジェクトを使ってみる`をクリックする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/62836ac6-0680-4a16-848f-f6b512c10a01.png" width="60%">　

- 任意のプロジェクト名をつけて、チェックボックス二つにチェックし続行をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/458bfc5c-b453-4f04-bf76-7a497194f256.png" width="60%">　

- Geminiは任意にチェックし続行をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/8e999b41-3f28-473c-988a-2ebefb7669b7.png" width="60%">　

― 任意にON/OFFにして続行をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/eb55d737-a99b-43c0-b08c-62405fb7557c.png" width="60%">　

- 今回は日本にし(特に理由はない)同意にチェックしプロジェクトを作成をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/48257af9-4628-4164-93dd-a1efef1b0325.png" width="60%">　

- プロジェクトが作成されるため、作成されたプロジェクトをクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/c2b01ca3-9ec1-4131-8e07-a119578b748a.png" width="60%">

- Unityのマークをクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/b6211a7d-87d9-41ce-b35b-73c466281f2b.png" width="60%">

- Androidアプリとして登録にチェックマークをいれ、任意のAndroidパッケージ名をつける
  - 今回作成対象のUnityゲームはWindowsデスクトップビルド用だが、Androidアプリとして登録(or Appleアプリとして登録)にチェックを入れてOK
      - **理由: ここで登録したときに取得できる設定ファイルが作成したFirebaseプロジェクトに接続するための情報が含まれている。UnityからFirebaseにアクセスるためにはこの設定ファイルが必要のため、この工程は必須** 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/bc9e5e61-0db1-4abc-94fe-4d4b2e4a2103.png" width="60%">


- 前の工程で作成した設定ファイルをUnity ~~ProjectのAssetsフォルダ~~ `Assets/StreamingAssets`配下に配置する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/1c10060f-268e-4dc6-bae7-72610b573eef.png" width="60%">

  - 補足:  ProjectのAssetsフォルダ配下に配置しUnityEditorで`Play`ボタンを押すと、以下の`StreamingAssets`配下に設定ファイルが存在しないエラーが出る。 → そのため **`Assets` > `StreamingAssets` に配置する必要がある**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/05a56a97-edba-4401-97ab-5cb182d96121.png" width="60%">


- UnityのSDKをダウンロード&解凍し、Unity EditorにFirestoreのパッケージ``をインポートし次へをクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/f5f88cdf-e4d0-45e9-bb49-121bf51dd368.png" width="60%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/a5a3784c-16fe-4509-85cb-586578d3efa4.png" width="60%">

- コンソールに進むをクリックする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/de1db0c4-e807-44a9-ace5-7b2f3a0eef90.png" width="60%">


## Step2: FirebaseコンソールからFireStore Databaseの作成
- 左のツリーの `構築` > `Firestore Database`をクリックする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/4b71ce42-c193-4e1b-8439-b7e3c65ff55e.png" width="60%">

- `データベースを作成`をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/bfced4a8-df83-4493-8234-4725411ff741.png" width="60%">

- データ格納場所は近くした方がいいのでロケーションを日本にし、`次へ`をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/dcd28e62-720a-492a-8101-0da04e2e2713.png" width="60%">

- 今回は動作確認に焦点を置きたいため、制限が少ないテストモードで作成する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/de6045b0-032e-4544-b2f9-2baf04d651a5.png" width="60%">

- テスト用のデータセットを作成する
    - コレクション名: `testCollection`
    - DocumentID : `testDocument`
    - フィールド: `testField`
    - タイプ: `string`
    - 値: `testData`

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/b7414d41-98e2-44a6-84b2-80eb7fd93a64.png" width="60%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/c4971f21-1120-4d1b-a639-0ce7ef2e55e9.png" width="60%">

## Step3: Unity Project から FireStoreのデータの読み取り
- `ReadFireStore.cs`スクリプトを作成し、ゲームオブジェクト`FireStore`を作成し、スクリプトをアタッチする

```cs:ReadFireStore.cs
using Firebase;
using Firebase.Firestore;
using Firebase.Extensions;
using UnityEngine;
public class ReadFireStore : MonoBehaviour
{
    private FirebaseFirestore db;

    // Step2で生成したコレクション名、ドキュメント名、フィールド名を設定
    private string collectionName = "testCollection";
    private string documentName = "testDocument";
    private string fieldName = "testField";
    void Start()
    {
        FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
        {
            if (task.IsCanceled)
            {
                Debug.LogError("Firebase initialization canceled.");
                return;
            }
            if (task.Exception != null)
            {
                Debug.LogError("Firebase initialization failed: " + task.Exception);
                return;
            }
            Debug.Log("Firebase initialized successfully.");
            // Firestoreインスタンスを取得
            db = FirebaseFirestore.DefaultInstance;
        });
    }
    public void ReadData()
    {
        if (db == null)
        {
            Debug.LogError("Firestore is not initialized yet.");
            return;
        }
        // ドキュメント参照を取得
        DocumentReference docRef = db.Collection(collectionName).Document(documentName);
        // データの取得
        docRef.GetSnapshotAsync().ContinueWithOnMainThread(task =>
        {
            if (task.IsFaulted)
            {
                Debug.LogError("Read data failed: " + task.Exception);
                return;
            }
            if (task.IsCanceled)
            {
                Debug.Log("Read data canceled.");
                return;
            }
            DocumentSnapshot snapshot = task.Result;
            if (snapshot.Exists)
            {
                // データの取得
                string fieldValue = snapshot.GetValue<string>(fieldName);
                // データの出力
                Debug.Log(fieldName + ": " + fieldValue);
            }
            else
            {
                Debug.LogWarning("Document does not exist.");
            }
        });
    }
}


```

- Unity Scene上にFireStoreのデータ読み込みボタンを配置し、ボタンクリック時に`ReadData`関数を呼ぶようにする。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/a3fc38ec-3ff8-4dab-9b69-df19dfbf43af.png" width="60%">


## 完成形
ボタンをクリックして、コンソールにて、FireStoreに登録したデータ`testData`を取得できることを確認する


![Videotogif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/8c8097ff-a86c-4996-aa23-f1b66d30592d.gif)