Unity勉強中!あこがれだったプログラマーに今からなろう!

昔あこがれだったプログラマー。今からでもUnityを勉強してみようと思い立ち、チャレンジ開始! Unity勉強メモや、悪戦苦闘な日々の記録です。

α版のデバッグをしよう(バグの原因特定と解決①):3Dアクションゲームを作ろう(20)

3Dアクションゲームのα版が完成しましたが、予想通り、多数のバグ🪳が発生😭

パッと見つかったのが以下の通り。
①回復用の魔法陣が一箇所でしか表示されない。
②一種類の敵の生成が止まってしまう。
③移動床に横から接触すると、移動床に引きずられてしまう。
④地面に沿うようにジャンプすると、ジャンプのままになってしまう。
⑤特定のタイミングで攻撃モーションのままになってしまう。そうなると移動不能状態になる。

嘆いていても仕方がないので、一つ一つ解決していこう。

「①回復用の魔法陣が一箇所でしか表示されない。」
魔法陣生成の仕組みは、特定のエリアにSphereCollider付きのObjectを設置してあり、そこにPlayerが侵入+PlayerのHPが9割以下であれば、パーティクルシステムで作成した魔法陣を再生するというもの。
それなのに、どのエリアのColliderに侵入しても、0番目のエリアで魔法陣が生成されてしまう😭
試しに、DebugでColliderが反応したエリア番号を表示させてみると、正しいエリア番号が表示される。
しかし、魔法陣が表示されるのはいつも0番目のエリア💦

色々と実験したけれど、解決の糸口が見つからない。

結局、いつものスタジオしまづさんのユニコンでジョニさんに相談し、ようやく解決策を見つけることができました。

修正前はOnTriggerEnterではエリア侵入のboolだけをたてて、魔法陣生成はUpdateで行っていた。
今にして思えば、これだと当然、他のエリアのObjectが反応することもあるわけで💦
なので、一番最初の0番がいつも魔法陣を生成するという、あたりまえな動きだった。
分かってしまえば解決方法は簡単で、魔法陣の生成をUpdateではなく、OnTriggerEnterで生成するように修正。
これだけで問題が解決しました🤣

てか、なんでUpdateで生成させていた、僕・・・_| ̄|○


「②一種類の敵の生成が止まってしまう。」
マップ上の敵は種類ごとに現在数がカウントされていて、設定した最大数に達するまでは、特定の間隔で生成され続ける仕組みになっている。
最大数に達しても、敵が倒されれば現在数が減り、生成が再開される。
なのに、


このフライングアイくんが最大数に達した段階で生成が止まってしまう。
生成されたフライングアイを全滅させてしまっても次が生成されない💦

しかも不思議なのは、Unity上のテストプレイでは正常に再生成されるのに、ビルドしたゲームだとこの状況が発生する💦

調べ方もわからないままに悩んでいたのだけど、結局、これもスタジオしまづさんのユニコンでの相談で、解決の糸口を見つけることができた。

敵の種類ごとの現在数をUIに表示するように修正して、再度ビルドして実験したみたところ、
フライングアイくんだけは倒しても現在数が減らないということがわかった。

現在数のカウントはGameManagerが管理しているが、加算は敵生成ObjectのEnemy Generatorスクリプトで行い、減算は各敵のControllerスクリプトで行っている。
そして、敵のControllerはスライムとオークは同じEnemy Controllerスクリプトだけど、フライングアイはBeholderControllerという別のスクリプトになっている。
そして、敵生成のEnemy Generatorはスライム・オーク・フライングアイと全てが同じスクリプトで生成させている。
その整合を取るために、生成した敵のComponentをtry文でystem.NullReferenceExceptionをトラップする方法で、生成した敵のControllerがEnemy ControllerとBeholderControllerのどちらか判定して設定する仕組みにしていた。

        try
          {
              gene_enemy.GetComponent<EnemyController>().enemyGenerator=this;
          } catch (System.NullReferenceException e)
          {
               gene_enemy.GetComponent<BeholderController>().enemyGenerator=this;
          }

このやり方でUnity上では問題なく動作してくれていたけれど、ここに問題があると仮定して、別の方法でControllerを判定するように修正してみた。

    [SerializeField] int GeneratorNo; //ここでGeneratorの番号を指定する。
    public GameObject Enemy1;
    [SerializeField]HostilityListManager hostilityListManager;
    [SerializeField] GameManager gameManager;

    void Start()
    {
        InvokeRepeating("EnemyGenerate",3f,15f);        
    }

    void EnemyGenerate()
    {

        if(gameManager.EnemyCount[GeneratorNo]<gameManager.MaxEnemy[GeneratorNo]) //指定した番号でGameManagerのカウントを識別。
         {
            GameObject gene_enemy=Instantiate(Enemy1,transform.position,Quaternion.identity);

            if(GeneratorNo==2) //生成する敵がこれで判定できる。
            {
         //倒された時に減算する変数を指定するために、Generatorの番号を敵のスクリプトに設定する。
                gene_enemy.GetComponent<BeholderController>().GeneratorNo=GeneratorNo; 
                gene_enemy.GetComponent<BeholderController>().itemManager=itemManager;
                gene_enemy.GetComponent<BeholderController>().enemyGenerator=this;
                gene_enemy.GetComponent<BeholderController>().gameManager=gameManager;
            }
            else
            {
         //倒された時に減算する変数を指定するために、Generatorの番号を敵のスクリプトに設定する。
                gene_enemy.GetComponent<EnemyController>().GeneratorNo=GeneratorNo;
                gene_enemy.GetComponent<EnemyController>().itemManager=itemManager;
                gene_enemy.GetComponent<EnemyController>().enemyGenerator=this;
                gene_enemy.GetComponent<EnemyController>().gameManager=gameManager;
            }

            gene_enemy.GetComponentInChildren<StatusManager>().hostilityListManager=hostilityListManager;
            gameManager.EnemyCount[GeneratorNo]++;
        }
    }

これでフライングアイくんを倒すと、代わりが正常に生成されるようになってくれました😆

②の様に、正常なものとバグになるものの二種がある場合は、まず「その二種の何が違いを生んでいるのか」を調べていくことが大切だという事を、早いうちに学べたのはとても良かったと思う。

それにしても、
Unity上のテストでは問題なく動作しても、ビルドすると思った通りに動作しなくなる処理があるんだね💦
これもとても勉強になったよ。
ほんと、早く解決できた良かった〜😅