Unityに関連する記事です

 この手順では、防衛用の味方キャラに攻撃範囲内にいる敵に対して一定時間ごとにダメージを与えるようにし、ダメージによって破壊される、というように順番に処理を実装します。
また攻撃範囲より敵キャラがいなくなってしまった場合には、攻撃の処理を停止する処理も合わせて実装します。

 以下の内容で順番に実装を進めていきます。


<実装動画 々況眸楼脇發謀┘ャラが侵入したら一定時間ごとに攻撃してダメージを与える>
動画ファイルへのリンク


<実装動画◆‥┘ャラが攻撃範囲外になったら攻撃を停止する>
動画ファイルへのリンク


手順12 ー味方キャラの攻撃処理と敵キャラのダメージ処理の実装ー
20.CharaController スクリプトの修正を行い、攻撃範囲内に侵入した敵キャラに一定時間ごとに攻撃する処理と、敵キャラがいなくなった場合に攻撃を停止する処理を実装する
21.EnemyController スクリプトの修正を行い、攻撃範囲内に侵入した敵キャラにダメージを与えて破壊する処理を実装する



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

 ・while 文とコルーチン・メソッドを組み合わせた処理の実装例
 ・OnTriggerExit2D メソッド
 ・Mathf.Clamp メソッド
 ・Tween.Kill メソッド



20.CharaController スクリプトの修正を行い、攻撃範囲内に侵入した敵キャラに一定時間ごとに攻撃する処理と、敵キャラがいなくなった場合に攻撃を停止する処理を実装する

1.設計


 一度に処理を実装するのではなく、防衛用のキャラ側の処理を実装し、その後、敵キャラ側の処理を実装します。
1つずつ順番に機能を追加していくことで不具合を見つけやすくします。また、前提となる処理を理解した上で先に進めることが出来ます。

 まずは防衛側の味方キャラにどのような処理が必要になるか、その場合には、どんな変数が必要で、どのように利用していけばよいかといった部分を考えて書きだしてみてください。
頭の中でのイメージを書き出すことが出来れば、それを元にプログラムのロジックを考えていくことが容易になります。
現在の CharaController スクリプトをみながら処理をイメージしてみましょう。
 
 攻撃範囲内については OnTriggerEnter2D メソッドにおいて実装済です。この処理の中で敵キャラをすぐに破壊してしまっていたため、
その部分を「一定時間ごと」に「敵を攻撃する」というロジックを考えていきます。

 一定時間ごと、というのは、簡単に考えても計測用の値と目標用の値の2つが必要になります。
値同士を比較することによって、一定時間を表現することができるようになるためです。
また一定時間を判定し、それを繰り返すことになりますので、繰り返し用の処理を考える必要もあります。

 敵を攻撃する、というのは、敵の体力を減らす、という状態になります。
現時点では敵にも体力となる値はありませんでの、まずは防衛用の味方キャラに攻撃力用の値を準備するようにします。
減らす処理自体は敵の体力が追加されてから実装することになりますので、まずは Debug.Log メソッドを活用して、攻撃を行っていることを確認しておくようにします。
この部分にあとで処理を実装するイメージです。

 まずはここまでを実装できるように、ロジックを考えてみましょう。


2.CharaController スクリプトを修正する


 設計の内容を元にロジックを考えて、それからスクリプトを修正します。
スクリプトを修正するのは、しっかりと処理のイメージが固まり、ロジックが完成してからになります。
いきなり処理を書いたり、教材通りに書けばいい、という形で進めてしまうと、後々に自分でロジックを考えることが出来なくなってしまいます。

 常に自分で処理を書く、という意識を持ちながら、処理の内容を理解しながら書いていくようにしてください。


CharaController.cs


 スクリプトを修正したらセーブを行います。


3.while 文とコルーチン・メソッドを組み合わせた処理の実装例


 while(ホワイル) 文は反復処理と呼ばれる処理です。条件を満たしている限り、繰り返し処理を行います。

 今回のケースでは条件が「isAttack の値が true の間」です。
よって、isAttack の値が false になるまではずっと繰り返されて終わることのない処理になります。


    public IEnumerator PrepareteAttack() {

        Debug.Log("攻撃準備開始");

        int timer = 0;

    // 攻撃中の間だけループ処理を繰り返す
        while (isAttack) {

            // TODO ゲームプレイ中のみ攻撃する

            timer++;
        
      // 攻撃のための待機時間が経過したら    
        if (timer > intervalAttackTime) {

        // 次の攻撃に備えて、待機時間のタイマーをリセット
                timer = 0;

        // 攻撃
                Attack();
                   
                // TODO 攻撃回数関連の処理をここに記述する

                
            }

      // 1フレーム処理を中断する(この処理を書き忘れると無限ループになり、Unity エディターが動かなくなって再起動することになります。注意!)
            yield return null;
        }
    }

 while 文内の処理は3つあり、1つは timer 変数の加算処理、もう1つは攻撃メソッドの実行処理です。
指定された値になるたび、攻撃メソッドを実行する制御を行っています。

 もう1つは yield による中断(待機・遅延)の処理です。 yield return null 1フレームだけ処理を中断します。

 そのため、この while 文による繰り返しの処理は次のような挙動になります。

 1.while 文の条件を満たしているか、確認する。満たしていない場合には、処理を終了する
 2.条件を満たしている場合には、timer 変数の値を加算する。
   その後、timer 変数の値と intervalAttackTime の値を if 文にて比較して、条件を満たしている場合には if 文内の処理(timer 変数のリセットと攻撃メソッドの呼び出し)を行う
 3.1フレーム待つ
 4.【1】の処理に戻る

 Update メソッドを利用していませんが、しっかりと一定の間隔で繰り返し攻撃を処理を実装することが出来ました。

 なお、while 文では処理を中断する処理を挟まないと繰り返しの処理が止まらなくなって、Unity のエディターが動かなくなります
こうなってしまうと再起動するしかなくなりますので、while 文は特に気を付けて作業してください


参考サイト
未確認飛行 C 様
反復処理
https://ufcpp.net/study/csharp/st_loop.html


 他にも自動的に攻撃を行うようにする処理は考えられます。色々な処理を試しておくことで処理の引き出しが広がり、
より多くの処理を実装できるようになりますので、いつも使っている処理だけではなく、新しい技術も取り入れていきましょう。


4.Chara ゲームオブジェクトの設定を行う


 Chara ゲームオブジェクトのインスペクターを確認し、新しく追加した変数に情報に設定が反映しているか確認してください。
初期値が入りますので新しく設定を変更する部分はありませんので、確認だけで問題ありません。

 isAttack 変数はスクリプト内で制御が入りますので、チェックなし(false)の状態で構いません。
また enemy 変数も同様で、OnTriggerEnter2D メソッドが実行されたタイミングで代入されますので、こちらも None のままで問題ありません。


インスペクター画像



 以上で設定は完了です。


5.ゲームを実行して動作を確認する


 処理の内容を把握してから、ゲームを実行して制御できているかを確認していきます。


<実装動画>
動画ファイルへのリンク


 一定時間ごとに Debug.Log メソッドが表示されれば繰り返し処理と攻撃処理の制御成功です。


6.問題点を修正する ーCharaController スクリプトを修正するー


 デバッグを行って処理を確認していくとわかりますが、OnTriggerEnter2D メソッドに置いて EnemyController スクリプトの情報を取得すると、
その情報をずっと保持したままになりますので、敵キャラが攻撃範囲外に出ていっても、ずっと攻撃をし続けるようになっています。

 こちらを修正することを考えます。

 OnTriggerExit2D メソッドという処理がありますので、こちらを活用しましょう。
このメソッドは侵入しているコライダーが侵入範囲外に出たときに1回だけ自動的に処理が実行されるメソッドです。
つまり、敵キャラが攻撃範囲外に出たタイミングで呼び出されますので、このメソッド内で繰り返しの処理を停止し、 EnemyController の情報を削除することが出来れば
結果として攻撃処理も停止するようになります。

 繰り返しの処理はどのようにして動いているか? 

 停止するにはどうすればいいのか?

このロジックをイメージして、処理を書いてみましょう。


CharaController.cs


 スクリプトを修正したらセーブを行います。


7.ゲームを実行して動作を確認する


 処理を修正しましたので、Chara ゲームオブジェクトのインスペクターを確認しながら処理を実行してみましょう。
どの処理が、どの部分を動かしているのかを理解しておくことがスクリプトの理解を深めることにもなります。


<実装動画>
動画ファイルへのリンク


 無事に制御できているか確認しておきましょう。


21.EnemyController スクリプトの修正を行い、攻撃範囲内に侵入した敵キャラにダメージを与えて破壊する処理を実装する

1.設計


 プログラムのロジックを考えるときは、実行したい処理をメソッドにまとめて用意し、それを必要なタイミングで呼び出すように考えます。
今回のケースであれば、呼び出したいタイミングは CharaController スクリプト側に TODO で記述してありますので、
あとはその処理を実装すればロジックが完成します。

 EnemyController スクリプト側に、CharaController スクリプト側から呼び出してもらうメソッドを実装しましょう。
メソッドには引数を設定できますので、CharaController スクリプト側に設定している attackPower の値を引数を通じて受け取ることで
EnemyController スクリプト側のメソッドに、attackPower の値が情報として届き、利用出来るようになります。

 敵の破壊処理に際してですが、敵の移動を実行している DOTween の DOPath メソッドは非同期処理で動いています。
そのため、DOPath メソッドを実行している敵キャラ自体が破壊されてしまっても、この処理自体が自動的に終了することはありません。
通常の同期処理によるプログラムと非同期処理によるプログラムにはこのような違いもあります。

 よって、敵キャラが破壊されたタイミングで適切に DOPath メソッドの処理を終了しておく必要があります。

 DOTween の処理は Tween という型によって動いています。処理の実行途中で処理を終了したい場合(あるいは一時停止したい場合など)は、
Tween 型の変数を用意しておき、その中に実行するメソッドを代入することによって、処理の制御が可能になりますので
敵の破壊処理を実装する場合、DOPath メソッドの実行処理にも修正が必要になります。


2.EnemyController スクリプトを修正する


 新しくダメージ計算用のメソッドと破壊処理用のメソッドを実装します。
 
これに伴い、Start メソッド内に処理の追加と修正があります。

 変数の宣言も新しく3つ準備しています。同じ項目同士(SerializeField属性 の変数)で並べているため、途中に差し込んでいます。

 今後の実装を見通し、TODO を残しておきます。こちらも順次、必要に応じて追記していきましょう。
自分で処理の流れを考えてみて、ここにはこんな処理が欲しいな、という部分には積極的に TODO を残しておくようにするとプログラムのロジックを考えやすくなります。


EnemyController.cs


 スクリプトを修正したらセーブをします。


3.<Mathf.Clampメソッド>


 Mathf クラスは、Unity が用意している、数学関数のメソッド処理をまとめてあるクラスです。通常の Math クラスと異なり、戻り値は float 型で用意されています。
このうち、Clamp メソッドは、「制御したい指定値を、指定した範囲内の最小値、最大値に収めてくれる(置き換えてくれる)」処理になります。

<メソッドの記法>
  制御したい指定値 = Mathf.Clamp(制御したい指定値, 最小値, 最大値);
 
 このメソッドを利用して、計算処理後の hp 変数の値を制限することが出来ます。
上記のメソッドの書式に、制御したい値を当てはめて処理を組み立ててみましょう。

  // Hp の値を減算した結果値を、最低値と最大値の範囲内に収まるようにして更新
  hp = Mathf.Clamp(hp -= amount, 0, maxHp);

 なおMathf.Clampメソッドにはオーバーロードがあり、引数の型は、float型とint型でそれぞれ利用が出来るようになっています。
hp 変数の型は int 型ですので、今回は自動的に int 型を利用しています。
Unity公式スクリプトリファレンス
Mathf - Clamp
https://docs.unity3d.com/jp/540/ScriptReference/Ma...


4.<Tween.Kill メソッド>


 DOTween に関連する処理になります。
Tween 型の変数を宣言することで、DOTweenの処理内容を変数に代入することが出来ます。

 DOTweenの処理は変数に代入せずとも実行できます。本来はそれだけで問題はないのですが、
Tween 型の変数に DOTween の処理を代入していることで、DOTweenの処理を一時停止させたり、再開したり、強制的に終了させることが出来るようになります。

 どのような場面で使用するかというと、無限ループの処理を終了させたり、一時停止して再開したりできます。
また、今回のように経路移動の処理の途中で敵キャラが破壊されてしまって、DOPath メソッドがすべて実行できなくなってしまうようなケースです。

 変数にDOTweenの処理を代入していない場合、動いている DOTween の処理を一時停止したり、再開したり、強制的に終了させる処理が実行できません

 DOTweenの処理を中断するには、Killメソッドを実行します。この処理を実行することで、今回であれば DOPath メソッドによる経路移動処理を終了させることが出来ます。

 private Tween tween;  // Tween 型の変数

  // Tween 型の変数には DOTween の処理を代入できる
     ↓
  // 各地点に向けて移動。今後この処理を制御するため、Tween 型の変数に DOPath メソッドの処理を代入しておく
  tween = transform.DOPath(paths, 1000 / moveSpeed).SetEase(Ease.Linear).OnWaypointChange(ChangeAnimeDirection);

 // DOTween の処理を破棄(終了)する
  tween.Kill();


5.Enemy ゲームオブジェクトの設定を行う


 EnemyController スクリプトの修正を行いましたので、Enemy ゲームオブジェクトのインスペクターを確認して設定を行います。

 maxHp 変数に最大HP の値を設定してください。デバッグ用に数値を大きくしたり、小さくしたりして確認しますので、
まずは最初は 1 にしておいて、攻撃処理→ダメージ計算処理→破壊処理が実行されるかを確認しましょう。


インスペクター画像


 
 以上で設定は完了です。


6.CharaController スクリプトを修正する


 EnemyController スクリプト側にダメージ計算用のメソッドと破壊処理のメソッドが実装できましたので、
最後に、このうちのダメージ計算用のメソッドの呼び出し処理を実装します。破壊処理はダメージ計算用のメソッド内で呼び出しがあるので、こちらからの呼び出しは不要です。

 TODO で記述されている部分になりますので、まずは自分で実装に挑戦してみてください。


CharaController.cs


 スクリプトを修正したらセーブを行います。


7.ゲームを実行して動作を確認する


 処理の流れを把握した上でゲームを実行して動作を確認していきます。

 敵の mapHp の値や防衛キャラの attackPower の値や intervalAttackTime の値を調整して
どのように処理が変わるのか、しっかりと内容を理解しておいてください。


<実装動画 々況眸楼脇發謀┘ャラが侵入したら一定時間ごとに攻撃してダメージを与える>
動画ファイルへのリンク


<実装動画◆‥┘ャラが攻撃範囲外になったら攻撃を停止する>
動画ファイルへのリンク


8.Enemy ゲームオブジェクトと PathTranSet ゲームオブジェクトをヒエラルキーから削除する


 デバッグ用の役割が終了しましたので、これらのゲームオブジェクトをヒエラルキーより削除してください。
次の手順では、Enemy ゲームオブジェクトのプレファブを利用していきます。



 以上でこの手順は終了です。

 次は 手順13 −敵キャラの自動生成処理の実装− です。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



プログラムの基礎学習

コード練習

技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

3Dトップビューアクション(白猫風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます