Unityに関連する記事です

 敵キャラの移動経路を視覚的にライン表示する機能を実装します。
この機能は Unity の持つ LineRenderer コンポーネントの機能を利用しています。

 移動経路の表示中には敵が移動を開始しないように制御処理を加えることも必要になります。
敵の生成→経路用のラインの生成→ラインの削除→敵の移動開始、という流れになりますので、
このロジックを考えて、どのようにすれば実装ができるのか、設計を詳細に練ることが大切です。


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


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

手順14 ー敵キャラの経路表示の自動生成処理の実装ー
24.経路用の PathLine ゲームオブジェクトを作成する
25.経路に合わせて自動的に PathLine ゲームオブジェクトを作成する処理を実装する



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

 ・マテリアルの作成
 ・LineRenderer コンポーネント
 ・Tween.Pause メソッド
 ・Tween.Play メソッド
 ・Listの使い方  Add メソッドー
 ・yield return StartCoroutine メソッドによる待機処理



24.経路用の PathLine ゲームオブジェクトを作成する

1.設計


 経路用の表示、といっても、それはゲーム画面でみた場合の動きです。
それを実際にゲームの処理、ロジックとしてどのように考えて実装していけばよいのかを検討します。

 このロジックを考える作業が非常に大変なのですが、これがプログラムを行うエンジニアに求められるスキルになります。
プログラマーとは、自分の考えられる引き出しの中から最適解を導きだしてそれをロジックとして設計し、ゲーム内に実装することが職務になります。
非常にクリエイティブかつ、論理的な考えを求められますので、教材を通じてロジカルな思考、発想、考え方を身につけていきましょう。
 


 今回の場合は、経路の矢印を1つのゲームオブジェクトとして作成する設計を検討します。
それを複数生成することによって、スタート地点からゴール地点までの経路をなぞるような演出にします。


2.PathLine ゲームオブジェクトを作成する


 矢印のゲームオブジェクトである PathLine ゲームオブジェクトを作成します。

 ヒエラルキーの空いている場所で右クリックをしてメニューを開き、Effects => Line を選択します。
LineRenderer コンポーネントがアタッチされてたゲームオブジェクトが作成されますので、名前を PathLine に変更します。


ヒエラルキー画像



インスペクター画像



 以上でこの手順は完成です。


3.PathLine 用の画像を取得し、マテリアルを作成する


 経路表示用の素材を用意します。矢印の画像を無料サイトなどから探して、Unity へインポートしてください。
TextureType は Sprite に変更しておきます。背景を透過して利用したいので、画像ファイルの拡張子は png ファイルのものにしてください。


インスペクター画像



 続いて、新しくマテリアルを1つ作成します。
Project 内、あるいは任意のフォルダ内で右クリックをしてメニューを開き、Create => Material を選択してください。
名前は PathArrow に変更します。

 Shader の設定を LegacyShagers / Particles / Additive に変更します。
画像ファイルを設定できる項目が表示されますので、先ほどインポートした矢印の画像ファイルをドラッグアンドドロップしてアサインしてください。
これで画像を利用したマテリアルが出来上がります。


インスペクター画像



 以上でマテリアルは完成です。


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


 PathLine ゲームオブジェクトの LineRenderer コンポーネントの設定を行います。
このコンポーネントは直線の画像を描画する機能を持っていますので、それを利用して矢印の画像を描画するようにします。

 Materials の Element 1 に Default-Line がアサインされていますので、この部分に先ほど作成した PathArrow マテリアルをドラッグアンドドロップしてアサインしてください。

 続いて、Additional Settings の Sorting Layer を Chara に設定します。これで背景の TileMap よりも優先順位が高くなり画面に表示されます。


インスペクター画像


 以上で設定は完了です。


5.DrawPathLine スクリプトを作成する


 LineRenderer コンポーネントの制御を行ってはじめて直線が描画されます。
DrawPathLine スクリプトを作成して、直線のラインを描画する処理を実装します。


DrawPathLine.cs

<= クリッすると開きます


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


6.<LineRenderer コンポーネントの機能>


 Line Renderer (ラインレンダラー) コンポーネントは、空間の2つ以上の点の配列をとることで、それぞれの間に直線を描きます。
公式サイトには 3D とありますが、2Dでも応して活用していくことが可能です。

参考サイト
Unity 公式マニュアル
LineRenderer
https://docs.unity3d.com/ja/current/Manual/class-L...
Unity 公式スクリプトリファレンス
LineRenderer
https://docs.unity3d.com/jp/current/ScriptReferenc...


 今回実装している変数やメソッドについてまとめておきます。
必ず自分でも調べて、自分の知識として吸収しておいてください。


1.LineRenderer.startWidth

 LineRenderer で描画するラインの幅のスタートのサイズを設定することができる変数です。


参考サイト
Unity 公式スクリプトリファレンス
LineRenderer.startWidth
https://docs.unity3d.com/jp/current/ScriptReferenc...


2.LineRenderer.endWidth

 LineRenderer で描画するラインの幅の最後のサイズを設定することができる変数です。


参考サイト
Unity 公式スクリプトリファレンス
LineRenderer.endWidth
https://docs.unity3d.com/jp/current/ScriptReferenc...


 これらの他にも、色を変更する変数や、曲線を描くための変数なども用意されています。


3.LineRenderer.positionCount

 LineRenderer で描画するラインの頂点数を設定したり、参照したりすることができる変数です。

  // 生成するラインの頂点数を設定(今回は始点と終点を1つずつ)
  lineRenderer.positionCount = drawPaths.Length;

 今回は代入処理を行い、頂点数の設定を行っています。drawPaths.Length の値は 2 ですので、ラインを生成するための頂点数を 2 に設定します。
つまり、始点と終点になります。この2つの頂点を結ぶことでラインを生成します。ここではそのための準備をしています。


参考サイト
Unity 公式スクリプトリファレンス
LineRenderer.positionCount
https://docs.unity3d.com/jp/current/ScriptReferenc...


4.LineRenderer.SetPositions

 ラインの頂点の位置をすべて設定するメソッドです。この処理によって描画処理が実行されます。
SetPosition メソッドという処理も用意されていますが、リファレンスにもあるように、複数のラインを描画する場合にはこちらの処理の利用するようにしてください。

  lineRenderer.SetPositions(drawPaths);

参考サイト
Unity 公式スクリプトリファレンス
LineRenderer.SetPositions
https://docs.unity3d.com/jp/current/ScriptReferenc...


 そのほかの活用事例を紹介しているサイトもたくさんありますので、自分でも検索してみてください。

参考サイト
はなちるのマイノート 様
【Unity】LineRendererをスクリプトから自由自在に操る
https://www.hanachiru-blog.com/entry/2020/10/05/12...


7.PathLine ゲームオブジェクトに DrawPathLine スクリプトをアタッチして設定を行う


 ヒエラルキーにある PathLine ゲームオブジェクトに、作成した DrawPathLine スクリプトをドラッグアンドドロップしてアタッチします。
アタッチした際には必ず対象のゲームオブジェクトのインスペクターを確認して、アタッチできているかを確認します。

 DrawPathLine スクリプトには設定項目は2か所ありますが、スクリプト内で初期値を設定しているため、特に設定しなくても問題ありません。
この値は、実際に矢印の描画が行われた際に調整する部分です。自分の用意した画像との兼ね合いで適宜変更してください。


インスペクター画像



 以上で設定は完了し、PathLine ゲームオブジェクトは完成です。


8.PathLine ゲームオブジェクトをプレファブにする


 完成した PathLine ゲームオブジェクトをプレファブにします。

 Prefabs フォルダへドラッグアンドドロップしてプレファブにしてください。
プレファブになったら、ヒエラルキーにある PathLine ゲームオブジェクトは削除してください。


25.経路に合わせて自動的に PathLine ゲームオブジェクトを作成する処理を実装する

1.設計


 1つのラインを作成して、曲がり角を用意して生成する方法と、複数の直線のラインを作成して、それをつなげていく方法があります。
1つのラインで作成をすると、画像が伸びてしまうため、今回は複数の直線のラインを作成する方法で実装を検討します。


ヒエラルキー画像



SceneビューとGameビュー画像



 プレファブにした PathLine ゲームオブジェクトをコーナーのたびに生成し、複数のラインを作っていることがわかります。
今回はこのラインの生成処理と、PathTranSet ゲームオブジェクトの移動経路の情報とを連動させて、A の位置から B の位置までを1つのラインとして、それを経路の順番ごとに生成処理する機能を実装します。
この処理は PathTranSet ゲームオブジェクトにアタッチされている PathData スクリプトの移動経路の情報である PathTranArray 変数が配列で管理されているため、それを上手く組み合せてロジックを組みます。

 具体的には、StartTran ゲームオブジェクトの地点から PathTran ゲームオブジェクトの地点までに1つのラインを作成します。
これは PathTranArray 配列の Element 0 => Element 1 に対してラインを作っています。

 それが完成したら、次は、Element 1 => Element 2 に対してラインを作成します。
これを最後のゴール地点になるまで繰り返すことによって、上記の画像のように複数のラインを作成して経路表示を実装しています。


<PathTranArray 変数の情報を活用する>


 この処理の実装には、敵キャラの移動処理にも大きくかかわっています。
どういうことかというと、ラインの表示が行われている間は、敵キャラの移動を一時的に停止しておくようにしないと、
ラインの表示中に敵キャラが移動をしてしまうことになるためです。

 タワーディフェンスゲームでは事前に敵の移動経路の情報をプレイヤーに提供し、それを元にプレイヤーは考える時間を作ります。
その後に敵キャラが実際に移動を開始するという流れになっていますので、これを実現するためには、ラインの生成処理だけではなく、
敵キャラの移動の制御処理も一緒に実装を行う必要があります。

 実際のラインの生成処理については、敵を生成する機能を持つスクリプトで制御する方法と、各敵キャラごとラインを生成する方法が考えられます。
今回は敵を生成する EnemyGenerator スクリプト側でラインを生成するように設計します。
これは、ライン用のゲームオブジェクトをプレファブとして登録することを考えてのことです。
EnemyGenerator スクリプトであれば1つ登録すれば済みますが、敵キャラに設定するとなると、すべての敵キャラごとにライン用のゲームオブジェクトのプレファブを登録する必要が生まれます。
10体いれば、10回アサインが必要です。もしもアサイン漏れがあればゲームが停止してしまう恐れもあります。

 そういった観点から考えて、今回は1回のアサインで済むように EnemyGenerator スクリプト内で、敵の生成に合わせて、その敵の移動経路の情報を利用して
ラインを生成するという制御で設計を考えていきます。


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


 どのようなロジックを組めば、ラインの生成処理が終了してから敵キャラが移動するようになるか考えてみましょう。

 DOTween の処理を利用して敵キャラを移動させていますので、その移動処理は tween 変数に代入されています。
そのため、移動の一時停止や再開の処理についても、DOPath メソッドによる移動処理を直接変更するのではなく、
この tween 変数にたいして処理を実行することで制御を行うことが可能です。


EnemyController.cs


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


3.<Tween.Pause メソッド>


 DOTween の Tween 処理を変数に代入しておくことにより、Kill メソッドの他にも制御を行うことが出来ます。

 Pause メソッドは Tween の処理を一時停止する命令です。この処理を行うことにより、Tween 型の変数内に代入されている実行中の DOTween の処理を一時停止出来ます。


    private Tween tween;


   // 各地点に向けて移動
    tween = transform.DOPath(paths, 1000 / moveSpeed).SetEase(Ease.Linear).OnWaypointChange(ChangeAnimeDirection);

   // 処理を一時停止
    PauseMove();


    /// <summary>
    /// 移動を一時停止
    /// </summary>
    public void PauseMove() {
        tween.Pause();
    }


4.<Tween.Play メソッド>


 一時停止している DOTween の処理は2つの方法で再開可能です。つまり、上手く使い分ける必要があります。
1つは今回利用している Play メソッドです。この命令では、一時停止して中断している DOTween の処理の続きから処理を再開できます。
もう1つは Restart メソッドです。この命令では続きからではなく、最初から処理の再生をやり直します。

 ロジックとしては、移動経路のラインを表示している間は Pause メソッドで移動の処理を一時停止しておいて、
ラインの表示が終了したタイミングでこの Play メソッドで移動を再開しています。

<EnemyGenerator.cs>
    /// <summary>
    /// ライン生成の準備
    /// </summary>
    private IEnumerator PreparateCreatePathLine(Vector3[] paths, EnemyController enemyController) {

    // ラインの生成と削除。この処理が終了するまでは、この処理より下の処理は実行されない
        yield return StartCoroutine(CreatePathLine(paths));

    // 敵の移動を再開
        enemyController.ResumeMove();
    }
 
<EnemyController.cs>
    /// <summary>
    /// 移動再開
    /// </summary>
    public void ResumeMove() {
        tween.Play();
    }

5.EnemyGenerator スクリプトを修正する


 ラインの生成処理については敵を生成する際に一緒に生成するよう設計しました。
それをロジックを考えてスクリプトを修正していきましょう。

 移動経路についてはラインの生成の際にも利用しますので、以前は EnemyController スクリプト内で経路情報を作成していましたが、
その処理を EnemyGenerator スクリプト側に移動し、作成した経路情報を EnemyController スクリプト側へ引数を通じて渡すようにロジックを考えてみてください。

 新しくメソッドを2つ作成しています。CreatePathLine メソッドの処理を自分でコメントを書いてみてください。


EnemyGenerator.cs


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


6.<Listの使い方  Add メソッドー>


 List クラスは <T> にジェネリック型(任意の型)を指定して、同じデータ型をまとめて管理するコレクション機能を持つクラスです。
配列と異なり、要素を自由に追加・削除できます。(要素数が可変する)

 List を利用するには宣言に合わせて初期化の処理が必要になります。

  // List の宣言と初期化
  List<DrawPathLine> drawPathLinesList = new List<DrawPathLine>();


List.Add(T型) メソッド

 Listの末尾に引数で指定した要素(データ)を追加します。
引数が T 型となっていますが、これは List を宣言した際に使った型が自動的に入ります。
今回は DrawPathLine 型の List を宣言していますので、Add メソッドの引数には DrawPathLine 型のみ指定できます。

 そのため、Listで宣言している型と同じ型であれば Add メソッドで List に要素を追加することが出来ます

 DrawPathLine drawPathLine = Instantiate(pathLinePrefab, transform.position, Quaternion.identity);

 drawPathLinesList.Add(drawPathLine);

 追加された要素は、自動的に List の最後に順番に追加されていきます。
例えば、drawPathLinesList がまだ1つも要素がなければ、drawPathLinesList[0] として1つ目に要素が追加されます。
そのあとに Add メソッドが実行された場合には、drawPathLinesList[1] として2つ目に要素が追加されます。


7.<yield return StartCoroutine メソッドによる待機処理>


 コルーチン(Coroutine)とは一定の時間や条件をもとに、処理を中断・再開・終了させることができる処理のことで、非同期処理と呼ばれます。

 コルーチンについての詳細な説明は割愛します。こちらの記事や、サイトで広く情報を取得できますので、そちらを参考にしてください。

XR-HU3様
【Unity】コルーチンで処理を中断・再開・停止させる方法を学ぶ
https://xr-hub.com/archives/20368


 コルーチンメソッド内には、yield を利用した処理を記述することができます。
例えば、数秒間の遅延処理や、条件達成までメインスレッドの処理を一時中断して待機させる処理などを、この yield を利用すると実装できます。

    /// <returns></returns>
    private IEnumerator PreparateCreatePathLine(Vector3[] paths) {

    // ラインの生成と削除。この処理が終了するまでは、この処理より下の処理は実行されない
        yield return StartCoroutine(CreatePathLine(paths));

    // 敵の移動を再開
        enemyController.ResumeMove();
    }

 通常のコルーチンメソッドの呼び出しと違いまして、呼び出す前に yield return があります
この場合、呼び出されたコルーチンメソッドの処理がすべて終了するまで、ここでプログラムを一時中断して待機させる、という処理が実行されます。

 呼び出すコルーチンメソッドの処理は、
「EnemyGenerator スクリプトにある CreatePathLine メソッドを実行する。そのメソッドの処理がすべて終了するまで、プログラムを一時中断させる」

という内容です。

 その結果、ラインの生成と削除が終了してから、はじめて次の処理(敵の移動を再開)が行われるという処理が実装されています。

 これは特に、CreatePathLine メソッドのようにコルーチンメソッドでの非同期処理を行う場合に効果的です。
通常のプログラムは同期処理ですのでその処理がすべて実行されてから次の処理に移行します。
ですが、今回の CreatePathLine メソッドはコルーチンメソッドですので、その処理の実行有無を判定して次に進む処理が行えません。

 そのため非同期処理が終了するのを待機するようにしないとラインの生成と削除の処理が終わってから次の処理に移行する、という手順でプログラムが進みません。
プログラムは上から下へと流れて処理されていきますが、このような非同期処理の場合には、中断処理を挟むことによってゲームの流れを制御しています。


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


 DrawPathLine スクリプトの情報をアサインする必要があります。


インスペクター画像



 このスクリプトは PathLine ゲームオブジェクトにアタッチされていますので、
Prefabs フォルダ内にある PathLine ゲームオブジェクトをドラッグアンドドロップしてアサインしてください。


インスペクター画像



 以上で設定は完了です。


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


 敵の生成速度が速いとライン表示が重なってしまうため、GameManager ゲームオブジェクトの GenerateIntervalTime 変数を調整して適宜な間隔で生成されるようにする部分がポイントです。
300 〜 500 前後で試してみるといいでしょう。

 デバッグを行う際には、自分で調整を行って、なるべく簡単に繰り返しデバッグが出来るようにしておくことが大切です。
これは今回の処理に限らず、すべてのデバッグに共通することですので、色々とやりやすい方法を考えておく必要があります。

 移動経路のラインがスタート地点から1つずつ順番に表示されて、しばらくしてからまた、スタート地点から1つずつ順番に削除されていれば制御成功です。
Sceneビューを見ながら、生成された敵がすぐに移動を開始せずに、移動経路のライン表示が終了してから移動を開始していることを確認してください。


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




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

 次は 手順15 −異なる生成地点での敵キャラの自動生成処理の実装− です。

コメントをかく


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

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

Menu



プログラムの基礎学習

コード練習

技術/知識(実装例)

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

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

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

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

レースゲーム(抜粋)

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

3D脱出ゲーム(抜粋)

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

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

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

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

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

VideoPlayer イベント連動の実装例

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

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

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

private



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

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