Unity 超初心者が Firebase でアプリ開発する際に必要になるスキル


こちらは [Unity #2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/unity2) の 8日目の記事です

また今回は、解説が長くなってしまうため前編と後編に分けることにしますmm
後編では、Firebaseの実装関連を全て [Firebase Advent Calendar 2020](https://qiita.com/advent-calendar/2020/firebase) の16日目に投稿予定の記事**『[UnityとFirebaseでアプリ開発する際にユーザーデータの取り扱い方まとめ](https://qiita.com/gremito/items/e630278bdb837948e15d)』**でまとめ~~ようと思います~~たので一緒にご覧ください。


## 概要

今回は、タイトルの通り超初心者がUnity/C#を学び、さらにFriebaseを使ってアプリ開発したい人向けとなります。
プログラミング初心者でもUnityは、書籍が豊富なだけでなく、[Asset Store](https://assetstore.unity.com/) や [Unity Learn](https://learn.unity.com/)、[Unity Japan YouTubeチャンネル](https://www.youtube.com/channel/UCCdskievdAtH6AtPeEfTqEg) などUnityコンテンツの制作・開発においてとてもサポートが豊富なので、熱意があれば小学生から高齢者まで幅広くもの作りができる、あらゆる可能性を持ったツールだと思います。

私は、[とあるサービスでUnityのインストラクター](https://www.sejuku.net/blog/109417)をやっているのですが、担当している生徒さんはほとんどプログラミング初心者でUnityを学びつつC#/プログラミングも学んで、その上で目的であるゲーム作りやVR/AR作りなども学んでいるため、学ぶことが多くお手上げ状態になってしまいます。
どんなに学びやすい環境でもスキルを身に付ける量が多いと、どうしてもモチベーションが下がってしまいますよね。

そこで今回は、初心者がUnityでiOS/Androidのアプリ開発を目指している方にだけターゲットになってしまいますが、[「どうぶつタワーバトル」や「飛べゴリラ」などのインディー/カジュアルゲーム](https://www.ntv.co.jp/matsukokaigi/articles/6b7oe9vpb2w23qdhm.html)の開発でコスパ最強な [mBaaS](https://boxil.jp/mag/a3651/) の [Firebase](https://firebase.google.com/) について、活用方法や必要になってくる知識のサポートについて解説していきたいと思います！


### 定義

各用語について本記事の定義をさせてください。

- **超初心者**
    - UnityとC#を技術書やネット記事などを参考にすでに何か作っている
- **プログラミング初心者**
    - ”入門”や”初心者”などが書かれている技術書をもとに何らかの言語を学んで何となく使える
- **アプリ開発**
    - 本記事ではiOS/Androidのアプリ開発のことで扱います


### ターゲット

改めてターゲットはこちらになります。

- Unity超初心者
- UnityでiOS/Androidのアプリ開発をやりたい方
- FirebaseをUnityでどう使うのかわからない方


### 前提

本記事を参考にするには次の項目が問題ないことをご確認ください。

- ボルドプラットフォームは、iOS/Androidに向けたアプリ開発が前提です。
- 各ツールのインストールや環境設定など済んでいる。
- C#の学習が、入門書の後半（例えば [独習 C#](https://www.shoeisha.co.jp/book/detail/9784798153827) だと「第7~9章 オブジェクト指向構文」）まで進んでいる。
- Unityがテーマなので、プログラミングの話はオブジェクト指向言語ベースです。
- Firebaseの前提知識は、公式ドキュメントで一部割愛させていただきます。


## やってほしいこと

今回は、[Firebase Authentication (Auth)](https://firebase.google.com/docs/auth) と [Firebase Realtime Database (Database)](https://firebase.google.com/docs/database) を活用するので、私が過去に書いた [FirebaseとUnityでアプリ開発（ハンズオンみたいなやつ）](https://qiita.com/gremito/items/dfb2080300955c5d5768)を参考に `FirebaseAuth.unitypackage` と `FirebaseDatabase.unitypackage` をUnityにインポートし、Firebaseの導入を済ませておいてください。

### キャッチアップ

また、公式ドキュメントをもとに一度Firebaseを実際に使ってどんなものなのか知ってもらいたいです。
次の項目を一通りやってみて、途中でわからなくて止まってしまっても全部確認してやってください🙏

- **Auth**
    - 1. [UnityでFirebase Authenticationを使ってみる](https://firebase.google.com/docs/auth/unity/start)
    - 2. [Unityでパスワード ベースのアカウントを使用してFirebase認証を行う](https://firebase.google.com/docs/auth/unity/password-auth)
    - 3. [Firebaseでユーザーを管理する](https://firebase.google.com/docs/auth/unity/manage-users)
- **Database**
    - 1. [UnityのFirebase Realtime Databaseを使ってみる](https://firebase.google.com/docs/database/unity/start)
    - 2. [データを保存する](https://firebase.google.com/docs/database/unity/save-data)
    - 3. [データの取得](https://firebase.google.com/docs/database/unity/retrieve-data)


## Firebase 活用方法

　<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/18fcbe9f-8b0c-a53d-3da3-6aac17ef7ab7.png">

今回、AuthとDatabaseを活用する理由ですが、カジュアルなゲームや2D/3Dのコンテンツの開発で**ユーザーデータ**の登録/取得が必要になる場面が多いため、他にもFirebaseの導入が必要かもしれませんが、まずは最低限の導入から進めることをオススメします。

アプリの要件次第ですが、例えばゲームアプリの開発でランキングシステムを実装するとします。
一端末で完結するアプリ（ノベルゲームや人狼ゲームなど）であれば [PlayerPrefs](https://docs.unity3d.com/ja/current/ScriptReference/PlayerPrefs.html) などを用いて、ローカルにデータを保持するだけで事足ります。
ですが、オンラインで様々なユーザーがランキングを争う要件となると、全ユーザーのゲームデータを管理する [サーバー](https://wa3.i-3-i.info/word144.html) が必要となります。

そこで、FirebaseのDatabaseでゲームデータを保持させ、アプリを使用するユーザーのみDatabaseへアクセスできるようにセキュリティの担保、およびユーザーを管理するAuthを使うことで、サーバーの開発と運用をやらなくて済みます。


### Auth

　<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/051eeafd-368a-12b0-76f4-453e56564919.png">

Databaseを使用するならAuth必須だと思っていいでしょう。
Firebaseはある一定から従量課金制になるので、使った分だけ請求が発生します。そのため、[誰でもアクセスでき（`".read": true`）誰でも書き込みでき（`".write": true`）る脆弱なDatabaseのルール](https://qiita.com/lacolaco/items/b068ab0cf19a26f0992d#rules%E3%81%AE%E5%9F%BA%E7%A4%8E)で運用してしまうと、Databaseが攻撃されて多額の請求が発生してしまう可能性が考えられます。

そのため、作るアプリを使用するユーザーのみアクセスと書き込みができる設定にしておけば不正アクセスを特定できるし、後からさらにセキュリティを強化することが可能です。


#### 認証方式

　<img width="500" src="https://firebase.google.com/docs/auth/images/auth-providers.png">


本来は、SNS連携でスマートにユーザー管理したいのですが、Unityの場合はiOS/Androidともに個別対応が必要で大変なので、今回も[前回同様](https://qiita.com/gremito/items/dfb2080300955c5d5768#auth)に[パスワードでの認証](https://firebase.google.com/docs/auth/unity/password-auth?hl=ja)を扱います。
　  
※[実装関連は後半へ続く](https://qiita.com/gremito/items/e630278bdb837948e15d)

### Database

　<img width="335" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/a361dd72-715c-0886-2b19-042fe1c7981d.png">

ユーザーデータをDatabaseに保存することで作る機能の幅がグッと広がります。
ゲームならランキング機能やゲームデータの共有機能、ゲーム以外でもフレンド機能などを開発できるようになります。

私が過去に開催したイベント [Unity Developer Jobs #1](https://unity-developer-jobs.connpass.com/event/138969/) でご登壇していただいた [@tktrvr](https://twitter.com/tktrvr) さんの [発表内容](https://speakerdeck.com/moomo/abataraibupei-xin-apuri-topia-falsekai-fa-falsehua-abataraibupei-xin-apuri-topia-falsekai-fa-falsehua) で、[アバターライブ配信プラットフォーム「トピア」](https://topia.tv/) のチャット・ギフトの実装は、Firebase Realtime Databaseで実装されているとのことでした。

　  
※[実装関連は後半へ続く](https://qiita.com/gremito/items/e630278bdb837948e15d)


### 公式ドキュメントにある各サンプルコード

さて、実際にAuthとDatabaseを扱って、Unity/C#の初心者さんはサンプルコードや公式ドキュメントの解説についてレベルが高く感じ、全然頭に入らないしどうしたらいいのかわからない状態になった方は少なくないんじゃないでしょうか。

ここからが本記事の本題でして、これから次の項目を一つ一つFirebaseに合わせて解説していきます。
Unity/C#の初心者さんは、どうキャッチアップすればUnityでFirebaseを使ってアプリ開発できるのか一緒に抑えていきましょう！

- **Json**
    - [データベースの構造化](https://firebase.google.com/docs/database/unity/structure-data)で扱う
- **非同期**
    - [アカウントの作成](https://firebase.google.com/docs/auth/unity/password-auth)と[データの保存](https://firebase.google.com/docs/database/unity/save-data)で扱う
- **ラムダ式**
    - 基本的な書き方とdelegateをセットに扱う


## Json（JavaScript Object Notation）

[Json](https://products.sint.co.jp/topsic/blog/json)は、1要素をKeyとValueで取り扱います。このValueでは、文字列や数値を取り扱える他に新たに要素を増やしたり、配列でもあたりを管理することができる上に人間がとても管理しやすいデータ型でもあります。

例えば、以下のようなテーブル情報があったとして、次のようなJsonフォーマットを文字列で管理することができます。
Json形式はフォーマットが存在するため、[JSON Pretty Linter Ver3](https://lab.syncer.jp/Tool/JSON-Viewer/)のようなWebツールを使って確認すると作業しやすいですね。

Usersテーブル

|id|name|point|
|:----|:----|:----|
|1|Tanaka|90|
|2|Sato|80|
|3|Yamada|70|
|4|Inoue|60|
↓

```json
{
  "Users": {
    "1": {
      "name": "Tanaka",
      "point": 90
    },
    "2": {
      "name": "Sato",
      "point": 80
    },
    "3": {
      "name": "Yamada",
      "point": 70
    },
    "4": {
      "name": "Inoue",
      "point": 60
    }
  }
}
```

　
FirebaseのDatabaseでは、JsonのようなKeyとValueでやり取りします。一般的なデータベース（MySQLやPostgreSQL）は、[SQL（Structured Query Language）](https://udemy.benesse.co.jp/development/system/intro-sql.html)をベースに設計されているため、SQLを学ぶ必要があります。

SQLの学習はとても難しいですが、JSONであればKeyとValueの設定さえ把握してしまえばいいので、JsonのWebツールなどを活用してサクッと身に付けましょう！


## 非同期

非同期は、以下のように『通常同期処理とは違って、メイン処理（メインスレッド）が終わっても別で処理（サブスレッド）が進んでいる。』だけ知り、それ以外で非同期を理解しようとしなくて大丈夫です。

```csharp
// 同期処理のサンプル
void Start() {
    Debug.Log("【メッセージ表示開始】");
    Debug.Log( Message() );
    Debug.Log("【メッセージ表示終了】");
}

string Message()
{
    var stg = "■-□-■-□-■-□-■-□-■-□\n";
    stg += " +。♪*。#+。♪*。#+。\n";
    stg += "Hello World!!\n";
    stg += " +。♪*。#+。♪*。#+。\n";
    stg += "■-□-■-□-■-□-■-□-■-□\n";
    return stg;
}

/**
 * [表示結果]
 * 
 * 【メッセージ表示開始】
 * ■-□-■-□-■-□-■-□-■-□
 *  +。♪*。#+。♪*。#+。
 * Hello World!!
 *  +。♪*。#+。♪*。#+。
 * ■-□-■-□-■-□-■-□-■-□
 * 【メッセージ表示終了】
 */

```

```csharp
// 非同期処理のサンプル
void Start() {
    Debug.Log("【メッセージ表示開始】");

    // 別処理（別スレッド）を作成
    Thread thread = new Thread(new ThreadStart(() =>
    {
        Debug.Log( Message() );
    }));
    // 別処理実行
    thread.Start();

    Debug.Log("【メッセージ表示終了】");
}

/**
 * [表示結果]
 * 
 * 【メッセージ表示開始】
 * 【メッセージ表示終了】
 * ■-□-■-□-■-□-■-□-■-□
 *  +。♪*。#+。♪*。#+。
 * Hello World!!
 *  +。♪*。#+。♪*。#+。
 * ■-□-■-□-■-□-■-□-■-□
 */

```

　
非同期処理の場合、上記のように処理の結果が変わります。
そのため、いつものようにメソッドを扱う感覚でプログラミングしてしまうと、タイミングによって処理結果がバラバラになってしまって不具合の原因を作りかねません。

非同期の場合、処理がどのタイミングで結果を出してくれるのか意識するために、[フローチャート](https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%AD%E3%83%BC%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88) や [シーケンス図](https://www.itsenka.com/contents/development/uml/sequence.html#:~:text=%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E5%9B%B3%E3%81%A8%E3%81%AF%E3%80%81%E3%82%AF%E3%83%A9%E3%82%B9,%E5%86%85%E5%AE%B9%E3%82%92%E8%A8%98%E8%BF%B0%E3%81%97%E3%81%BE%E3%81%99%E3%80%82) を書きながらプログラミングするとよいでしょう！


### どこで使うのか

非同期処理が必要になる箇所ですが、Firebaseが提供している `*****Async( ... ).ContinueWith( task => { 【ここの処理全て非同期処理】 } )` とAsyncが付いているメソッド全てになります。

Authでは、アカウントの作成（ `CreateUserWithEmailAndPasswordAsync ` ）とログイン（ `SignInWithEmailAndPasswordAsync` ）などで非同期処理が求められ、Databaseでは、データの取得（ `GetValueAsync` ）で非同期処理が求められます。


### 難しいので使い方がわかればいい

　<a href="https://gihyo.jp/book/2013/978-4-7741-5828-0"><img width="150" src="https://gihyo.jp/assets/images/cover/2013/thumb/TH320_9784774158280.jpg"></a>　<a href="https://www.oreilly.co.jp/books/9784873116044/"><img width="150" src="https://www.oreilly.co.jp/books/images/picture978-4-87311-604-4.gif"></a>

各プログラミング言語で非同期をテーマにした書籍が出ているぐらい、初心者ベテラン関係なく、非同期はとても難しいです。なので、最低限扱えるレベル学習するだけで大丈夫ですー


### Unityでの非同期の歴史

Unityの非同期には歴史がありまして、その辺は [@4_mio_11](https://twitter.com/4_mio_11) さんの [古来よりUnity非同期を実現していたコルーチンとは何者か？](https://qiita.com/4_mio_11/items/3030f9a39f59cd68f705) を参考にされてください。

## ラムダ式(Lambda Expression)

先ほど解説で出た `ContinueWith` メソッドの引数＝ラムダ式（[無名関数](https://ja.wikipedia.org/wiki/%E7%84%A1%E5%90%8D%E9%96%A2%E6%95%B0)）になります。
これも非同期同様に難しい分類なので、書き方と扱い方さえ把握すれば理解しようとしなくていいです。

ラムダ式は以下のような書き方で、ソースコードを簡略化することができます。

```csharp
// 通常のメソッド
int Add(int a, int b) {
    return a + b;
}

// ラムダ式
(int a, int b) => { return a + b; };
```

　
ラムダが無名関数と言われているように、ラムダ式になるとメソッド名と返り値の型を明示しなくてもプログラミングとして動きます。

さらに知りたい方は、[@toRisouP](https://twitter.com/toRisouP) さんの [【C#】わかった"つもり"になれる「ラムダ式」解説](https://qiita.com/toRisouP/items/98cc4966d392b7f21c30) を参考にされてください。


## さいごに

いかがだったでしょうか、個人的にFirebaseを扱うことでキャッチアップの量が増えてしまいますが、ここまで解説した最低限の範囲を学んで、Firebaseを用いて作っているアプリにユーザーデータを保存して取得できる機能が作れたら、Unity超初心者から卒業してるレベルじゃないでしょうか。

実装内容は、全て後編の [Firebase Advent Calendar 2020](https://qiita.com/advent-calendar/2020/firebase) の16日目に投稿予定の記事**『[UnityとFirebaseでアプリ開発する際にユーザーデータの取り扱い方まとめ](https://qiita.com/gremito/items/e630278bdb837948e15d)』**でまとめさせていただき~~ます~~ましたmm


### あくまでも参考程度

　<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/aacfddb5-74a5-4c21-dd55-da5f138e110f.png">

ちなみに公式ドキュメントのサンプルコードは、そのままでは扱えないコードを記載していることがためにあります。
上記のように変なところに閉じブロックがあったり、Unityではないですが、過去に[iOSのネイティブアプリでFirebaseを導入した際にサンプルコードだけではエラーになって](https://qiita.com/gremito/items/d14c21e2591e3223c5b9)調査しながら組み込んだことがありました。

このように、公式ドキュメントであっても全て正しいわけではなかったりするので、『公式のサンプルコードなのにエラーになるなあ、日本語記事は見つからないけど海外の記事に似たようなエラーの人がいるみたい。翻訳してもわからないから[直接公式に問い合わせ](https://firebase.google.com/support)しよー』ぐらいの感覚で気楽にやらないとやっていけませんので笑