i-school - 2Dタップシューティングゲーム 手順28
 おつかれさまでした!
前回の手順27までで、基礎編の実装は終了になりました。

 この手順ではいままでの実装の振り返りを行うとともに、次のステップへ向かうための学習意識の準備を行います。

手順28 −実装全体の振り返り−
59.設計について考える
60.実装した処理の内容を読み返して理解を深める



 新しい学習内容は、以下の通りです。

 ・Start メソッドと Update メソッドの利用方法を考える
 ・Start メソッドに依存しない設計



59.設計について考える

1.スクリプトの設計について


 現在作成してあるスクリプトを見直しながら、その設計方法について見直しをしていきます。

 この教材では、各手順の最初には必ず設計の方向性やロジックの考え方などを記述しています。
今はこれを解説として読みながら進めていると思いますが、自分でゲームを考えて設計を行っていく、ということは
この手順をすべて自分で考えて、ロジックを組める状態にすることになります。

 日本語をいかにプログラムとして置き換えてロジカルに考えていけるか、その訓練だと思って学習してください。
もう一度読み返してみてもいいでしょう。


2.Start メソッドと Update メソッドの利用方法を考える


 Unity で用意してある Start メソッドと Update メソッドは便利なメソッドです。
新しくスクリプトを作成した際にも最初から記述されていますので、それを利用することも多いでしょう。

 ただし、これらのメソッドの利用も、しっかりと考えた上で使っていくようにしてください
いくつかある設計方法の1つとして、必要に応じて利用をすることは問題ありませんが、
必ずこのメソッドを利用しなければなければならない、ということはありません。

 設計内容が増えていくに際し、必要に応じて処理を書き換える必要もあります。
例えば、最初は Start メソッドで実行していた処理を別のメソッドに移行したり、
Start メソッドの名前を別のメソッドに書き換えたりといったことです。
できればそういったことも見越して設計を行っておくことで、後々の変更も楽になります。

 一度 Start メソッドに処理を書いたから、Update メソッドがあるから、というような
あやふやな理由でこれらのメソッドを利用することは徐々に避けていくように考えてください



 出来ることであれば、新しく作成したスクリプトでは、一度、Start メソッドと Update メソッドを削除してみてください。
何もない状態から始めることで、フラットな目線で処理を記述出来るようになります。

 スクリプトにロジックを記述していく過程で必要に合わせてこれらのメソッドを復活させればよいです。
そうすれば本当に必要な時にだけ、Start メソッドと Update メソッドを利用した処理を記述することが出来るようになります。

 こういった視点でロジックを考えられるようになると、柔軟な処理をイメージして記述していくことが可能になります。


3.Start メソッドに依存しない設計


 今回は途中で何度か Start メソッドを別のメソッドに作り変えて、外部のスクリプトから呼び出して実行する処理に変更しました。
現在のスクリプトを確認してもらうと分かりますが、Start メソッドが記述されているのは GameManager スクリプトただ1つです。
見直してみてください。

 これはどういうことかというと、ゲームを実行した際に最初に実行される Start メソッドが1つだけ存在していることになりますので、
常に、この GameManager スクリプトの Start メソッドからゲームの処理が開始される、ということになります。つまり、そういった設計を意図して作っています



 複数のスクリプトに Start メソッドが記述されている場合、Unity では、どのスクリプトの Start メソッドを実行する、という保証がありません。
例えば、A 〜 D までの4つのスクリプトにそれぞれ Start メソッドがあった場合、最初にゲームを実行した際には A のスクリプトの Start メソッドが実行されたものの、
次にゲームを実行した際には C のスクリプトの Start メソッドが実行された、というように、Start メソッドを実行するタイミングは同じであっても
処理される順番が完全に Unity 側に依存した処理になります。そのため、こちらが考えている順番通りに毎回 Start メソッドが実行されることはありません

 これを、すべてのスクリプトを見た時に、B のスクリプトにだけ Start メソッドがあったとしたら、いかがでしょうか。
1つしかないので、必ず、この Start メソッドが一番に実行されることが確定されます。
そしてこれは設計を行う際に検討しておくことで、こういった処理になるように、こちらで考えながら作り上げていくことが出来ます。


 
 Start メソッドが1つだけ、という状態を作りだすことが出来れば、常にゲームを実行した際にはこの Start メソッドから処理が開始されることになります。
そのため、自分が考えた順番で Start メソッド内に処理を記述することで、必ずその順番で処理が実行されることも確定されます

 現在の GameManager スクリプトの Start メソッドを確認してみてください。
 
<GameManager スクリプトの Startメソッド>
  void Start()
    {
        // ゲーム終了の判定を、「ゲームが終了していない」状態にする
        SwitchGameUp(false);

        // DefenseBase スクリプトに用意した、DefenseBase の設定を行うための SetUpDefenseBase メソッドを呼び出す。引数として GameManager の情報を渡す
        defenseBase.SetUpDefenseBase(this);

        // PlayerController スクリプトに用意した、PlayerController の設定を行うための SetUpPlayer メソッドを呼び出す。引数として GameManager の情報を渡す
        playerController.SetUpPlayer(this);

        // EnemyGeneratorの初期設定
        enemyGenerator.SetUpEnemyGenerator(this);

    // TransformHelper スクリプトの temporaryObjectContainerTran 変数に情報を渡す
        TransformHelper.SetTemporaryObjectContainerTran(temporaryObjectContainerTran);

        // GameClearSet ゲームオブジェクトを見えない状態にする
        uiManager.HideGameClearSet();

        // GameOverSet ゲームオブジェクトを見えない状態にする
        uiManager.HideGameOverSet();
    }

 いかがでしょうか。現在までに作成してあるすべてのスクリプトに対して、1つずつ順番に処理が実行されていることが分かります。
そのため、この順番に処理が実行されていくことが確定していますので、複数の Start メソッドがあったときのように、
どの処理が先に実行されるか、そういった心配は全くありません。自分のイメージ通りの処理が実際に処理されていることになります。



 こういった設計にして処理を記述できる利点は、こちらが考えた処理通りに実行されていくという以外にもいくつかあります。

 1つはエラーを発見しやすくなる、ということです。

 例えば、enemyGenerator.SetUpEnemyGenerator(this); というメソッドが実行された際にエラーが出たとします。
その場合、この処理以前の処理はすべて問題なく動いていることが判明します。
何故ならば、途中で処理が止まることがなかったのでこのメソッドまで実行された、ということが確定しているからです。
つまり、このメソッド以前の処理に問題がない、ということがわかれば問題の切り分けが出来ていますので、エラーの原因となる場所の特定が容易になります。



 もう1つは、処理の順番を組み立てやすくなる、ということです。 
ゲームを実行すると Start メソッドの順番通りに処理が動いていく、ということは
処理が終了した時点の情報を確認しながら、どの処理の後にこの処理を入れたい、というイメージがわきやすく、
実際に記述する際にも、記述する対象となる場所の把握が容易になります。

 例えば、PlayerControler の SetUpPlayer メソッドが実行されて、必要な情報が設定されてから
その設定した情報を利用した処理を記述したい、という場合であれば、このSetUpPlayer メソッドよりも下に処理を追加すれば
自分が意図している順番通りに処理が動く、ということが分かります。



 とはいえ、最初からこのように設計が行えるわけではありません。
ですが、かといって、考えずにいてはいつまでたってもこういった設計方法を構築することが出来ません

 少しずつ、処理の内容を理解しながら、処理全体の流れを確認して、どうしたら上手く処理を設計できるのか、
そういう意識を常に持ってロジックを考えていくようにしてください。

 学習時間は非常にかかりますが、ロジックの構築や設計を行うことがエンジニアの仕事になりますので、
毎日の学習を、こういった点に意識を向けて繰り返し行うことによって、着実に自分のスキルとして培っていきましょう。


60.実装した処理の内容を読み返して理解を深める


 自分で記述したスクリプトを見直してみましょう

 もしも処理内にコメントがない部分があったら、日本語のコメントを処理の上に記述してみてください。
しっかりと処理の内容が記述できれば、処理が理解できていると考えて問題ありません。

 逆にコメントが記述できない処理がある場合には、その処理の復習を行いましょう。
理解を深めるためには、何回も処理を読み解き、書くしか方法はありません

 好きこそものの上手なれ、という言葉通り、プログラムを好きになれるように楽しんで学習をしてください。
勉強しなきゃ、やらなきゃ、という感覚が強いと気持ち的にも大変ですので、継続的な学習が難しくなります。

 
 以上で基礎編の実装は終了です。
おつかれさまでした。

 次は 発展編の実装手順を考える です。