サイバーエージェント　プロトスプリントリーグで学んだことまとめてみた　第1弾

# はじめに
今年の夏，サイバーエージェントのプロトスプリントリーグに参加してきました！テーマ発表からの準備期間が1週間，実際の開発期間は3日間でした．
チームメンバーのUnityの知見が多く，この期間中だけでたっっくさんのことを学習させていただきました．本当にありがとうございました．

今回はこれらのまとめになります．自分用のメモで書いている部分が多いので，URL紹介が多くなっているかもしれません．また，サンプルコードは一部省略していたり，操作確認をしていないためそのままコピペするとエラーになる場合があります．ご了承ください．

また，今回のプロトスプリントリーグで開発した作品はこちらになります．
[ChargeCat](https://unityroom.com/games/chargecat)
<font color="red">ぜひ遊んでください！！！！</font>

### 対象者
Unityの入門書を読み終えた後に，実際に何か開発したことがある方におすすめです．
まだ何も作ってないよという方でも，一度読んでみて，「これ実装したいけどなんかあの記事であったような...」となってもらえれば嬉しいです．

# 目次
[1. enum](#1-enum)
[2. UniTask](#2-unitask)
[3. DOTween](#3-dotween)
[4. UniRx](#4-unirx)
[5. プロパティ](#5-プロパティ)
[6. TrygetComponent](#6-trygetcomponent)
[7. Cinemachineでカメラの範囲指定](#7-cinemachineでカメラの範囲指定)
[最後に](#最後に)

# 1. enum
最初に紹介するのはenumです．これはご存知の方が多いかもしれない...
私的に1番わかりやすかった記事を紹介させていただきます．
[【初心者Unity】Enumを使ってゲーム中の状態や条件をわかりやすく管理しよう](https://tech.pjin.jp/blog/2021/03/31/unity_howto_enum/)

少し自分の言葉でもまとめます．
まず，ゲーム内の季節を入れる変数seasonがあるとします．seasonが0だったら春，1だったら夏...という設定です．
個人でかつ短期間で作る場合はこれでも良いのかもしれませんが，個人開発でブランクがあったり，チーム開発となると，seasonに0〜3以外を代入したり，どの数字がなんの季節かをいちいち確認しないといけないなんてことがあると思います．
こういう時にenumを使いましょう．事前に，enumに4つの季節を入れておけば，seasonに予期せぬ値が入ることはありませんし，seasonに夏を代入するときも，対応する値を確認せずに済みます．(おそらく補完機能が働いてくれるでしょう．)

ゲームの開始前orプレイ中or終了を監視したい時にも使えそうですね．
```cs:Hoge.cs
public enum GameState {
    BeforeStart,  // ゲーム開始前
    Playsing,     // ゲームプレイ中
    Finish,       // ゲーム終了
    Pause         // 一時停止中
}
```

# 2. UniTask
◯秒後にこれを実行したいって時，Time.deltaTimeを使ってませんか？△がtrueになるまで待つ処理を長く書いてしまうことありませんか？これを短くかけてしまうのがUniTaskです．
[「待つ」処理を超簡単にかけるUniTask導入](https://zenn.dev/wappaboy/articles/unitask-starter)
ぜひ上記のサイトをご覧ください，とてもわかりやすくまとめてくださっています．

使える場面としては
・一定時間ごとに表示するものを変えたい時
・ゲームが開始されるまで，プレイヤーなどの操作ができないようにしたい時(さっきのenumとも組み合わせられますね)
などなど...多くの場面で活躍することでしょう．

+α：[【初心者向け】UniTaskとコルーチンの違いを理解しよう](https://shibuya24.info/entry/unity-unitask-coroutine)

# 3. DOTween
オブジェクトの座標が◯◯になるまで△秒で移動させたい！だんだん透明にさせて，◻︎秒後には完全に透明にしたい！を簡単に書けてしまうのがDoTweenです．(読み方はドゥートゥイーン派とドットゥイーン派があるようで，笑)
[Unity DOTween 入門](https://qiita.com/broken55/items/df152c061da759ad1471)
上記のサイトにDOTweenの使い方はもちろん，実際の挙動も載せてくださっています．後半のOnなんたらはなんぞやという方はこちらを．
[DOTween完全に理解するその6 イベント編](https://qiita.com/BEATnonanka/items/a8c63df029f45ecf869d)

どうでしょうか，なんじゃこりゃ〜！ですよね．しかも瞬間移動じゃなくて本当に移動なんですよ(？)．過去に◯秒で◻︎まで移動するというのを実装しようとした時，瞬間移動しかしてくれなかったので，これを知っていたら...と思いました．<font color="red">今ある自分の知識だけで実装しようとせず，ネットで調べると案外楽な実装方法がヒットするかもしれません．</font>

ちなみにDOTweenとUniTaskを組み合わせることで，ほんの一例ですが，テキストをフェードインさせる→数秒待つ→テキストをフェイドアウトさせる　というのもできます．感動のエンディング作りをする際にいかがでしょうか．

# 4. UniRx
UniRxについては，1冊の本が出ているくらい奥深いので([UniRx/UniTask完全理解 より高度なUnity C#プログラミング](https://www.amazon.co.jp/UniRx-UniTask%E5%AE%8C%E5%85%A8%E7%90%86%E8%A7%A3-%E3%82%88%E3%82%8A%E9%AB%98%E5%BA%A6%E3%81%AAUnity-C-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/dp/4048930753))，ここではYouTubeで見つけたすぐ使えるテクニックを紹介します．
参考動画：[UniRxってどんなものかを解説しました。 今日から使えるワンポイントテクニック！](https://www.youtube.com/watch?v=RkiNH9UqU_Y)]  ※投稿日が3年前なので，変更点がある可能性あり

参考動画を見ていただくのが1番ですが，この動画を見てできることは，<font color="red">ある変数の値が変わった時，任意の関数を実行できるコードが簡単に書ける</font>というものです．例えば，残りHPの値が変わった時，textに変更後のHPを反映させなければなりません．
```cs:PlayerCore.cs
// 一部のコードは省略
using UniRx

public class PlayerCore : MonoBehaviour
{
    // int型のhpに初期値100を代入．このhpは監視対象になる．
    public ReactiveProperty<int> hp = new ReactiveProperty<int>(100);
} 
```

```cs:PlayerUI.cs
public class PlayerUI : MonoBehaviour
{
    public Text hpText;
    public PlayerCore playerCore;

    private void Start()
    {
        // PlayerCoreのhpの値が変化したら，UpdateHP()が実行される
        playerCore.hp.Subscribe(hp => UpdateHP(hp));
    }

    public void UpdateHP(int hp)
    {
        hpText.text = "HP:" + hp;
    }
}
```
私自身このコードのすごいと思うのが，HPが変化した時にもう一つ別の処理をしたいという場面があるとします．その時は別のクラスに
```cs
// 引数がない関数の実行
playerCore.hp.Subscribe(_ => HogeHoge());
```
と記載すれば実装でき，PlayerCoreに何も書き加えなくて良いのです．これはコードの読みやすさに繋がると思います．

もう一つ別の動画で紹介されていたのは，スペースキーを押したら2秒以上は押しても無効になるコードをUniRxで書くという動画です．これはイマイチ別の使用方法が思いついていないので，紹介だけしておきます．
参考動画：[#2 今日から使えるワンポイントテクニック！連打防止](https://www.youtube.com/watch?v=mKXTyjy0jKo&t=0s)

どこのタイミングでUniRx/UniTask完全理解は読んでみたいですが，調べたい時に辞書として使うことが多いそうです．

# 5. プロパティ
スクリプト間で変数の値を共有する時，よくprivateで宣言してSet関数とGet関数を作るというのがあります．これの簡単な書き方を紹介します．
```cs:ScriptA.cs
public class ScriptA : MonoBehaviour
{
    public int Score {get; set;}
}
```

```cs:ScriptB.cs
public class ScriptB : MonoBehaviour
{
    private ScriptA scriptA;

    void Start()
    {
        this.scriptA = this.GetComponent<ScriptA>();
        int i = scriptA.Score; // ゲッター。Scoreにsetされてる値を取得する
        scriptA.Score = 10; // セッター。Scoreに格納する値を書き換える
    }
}
```
注目すべきは
```cs:ScriptA.cs
    public int Score {get; set;}
```
です．省略せずに書くと，
```cs
    public int GetScore()
    {
        return score;
    }

    //スコアのセッター
    public void SetScore(int value)
    {
        score = value;
    }
```
となります．8行以上のコードが1行で書けてしまいますね．初見で見た時は？？？でしたが，意味を調べるとSet関数とGet関数が省略されたものでした．

参考サイト：[プロパティで安全に変数を共有する方法](https://naoyu.dev/%E3%80%90unity%E3%80%91%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%A7%E5%AE%89%E5%85%A8%E3%81%AB%E5%A4%89%E6%95%B0%E3%82%92%E5%85%B1%E6%9C%89%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)

# 6. TryGetComponent
みなさんGetComponentは使用したことがあると思います．チーム開発では特に，このGetComponentで取得したいものが取得できなかった時のエラーを回避するため，
```cs:Chapter6A.cs
public void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.GetComponent<BoxCollider2D>() == null)
    {
        // エラー時の処理
    } else 
    {
        collision.GetComponent<BoxCollider2D>().enabled = false;
    }

}
```
このように書くと思います．ここで，TrygetComponentを使うと
```cs:Chapter6B.cs
public void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.TryGetComponent<BoxCollider2D>(out var boxCollider))
    {
        boxCollider.enabled = false;
    }
}
```
と短く書くことができます．これは，GetComponent<BoxCollider2D>の取得にTryして，失敗ならfalse，成功したら取得したBoxCollider2DをboxColliderに入れてtrueを返します．
if文が短くなるのはもちろん，取得したらすぐに変数に入れてくれるのも良い点です．

# 7. Cinemachineでカメラの範囲指定
MainCameraでキャラクターを追うようにできた！その後，ステージの外が映らないようにも設定する必要があります．よし！じゃあ各ステージの四角形の頂点の座標を入力して，その内側映らないようにするスクリプト書こうと思った方いませんか...(自分です)
これ，ステージの端の座標を調べるのがかなり面倒でした．
しかし，カメラが動く範囲を簡単に設定できる方法があります．
参考サイト(キャラクター追従の方法)
[【Unity】Cinemachineで2Dゲームのプレイヤーにカメラを追従させる](https://nekojara.city/unity-cinemachine-2d#Cinemachine%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88)
参考サイト(カメラの範囲指定の方法)
[【Unity】Cinemachineで2Dカメラの表示範囲を制限する](https://nekojara.city/unity-cinemachine-2d-limit#%E7%A7%BB%E5%8B%95%E7%AF%84%E5%9B%B2%E3%81%AE%E3%82%B3%E3%83%A9%E3%82%A4%E3%83%80%E3%83%BC%E8%A8%AD%E5%AE%9A)

# 最後に
7つ紹介しましたがいかがでしたか！！
もし知らないものがあってお役に立てたのなら幸いです．私も書きながらですがかなり勉強になりました．まだまだ学べたことはたくさんあるので，また時間がある時に書こうと思います．