Unityで敵キャラを登場させて、目的地に移動させる

今回は、Unityで目的地に移動する敵キャラを作ってみようと思います。

まずは敵キャラをAsset Storeで探してインポートしてください。

3Dモデル→人型→その他→Zombie

をインポートしてみました。

インポートしたZombieのプレハブをRig→Humanoidで人型にしてシーンに設置します。

敵を目的地に移動させる記事の敵キャラクターのインスペクタ

上のようにAnimatorのApply Root Motionのチェックを外しアニメーションの動きを移動値に反映させないようにします。

スポンサーリンク
スポンサーリンク

敵キャラクターにコンポーネントを追加する

現時点ではAnimator Controllerの設定をしていなかったり、ゾンビを動かすCharacter Controllerを追加していないので、石造のように動きません。

まずはCharacter Controllerを設定して、当たり判定の範囲を調整しましょう。

敵2

これでスクリプトからCharacter Controllerの機能を使ってゾンビを操作する準備が出来ました。

次はアニメーションの状態と遷移を作成していきます。

Zombieフォルダ内にZombie Controllerという名前のAnimator Controllerを作成します。

敵3

Zombie Controllerをダブルクリックしアニメーション遷移画面を表示させます。

敵4

上の画像の+を押して、Float型のアニメーションパラメータSpeedを追加し、右クリック→Create State→EmptyでIdleとWalkの二つの状態を作ります。

敵5

IdleからWalk、WalkからIdleへ状態を選択して右クリック→Make Transitionしアニメーション遷移を作成します。
それぞれの遷移条件をSpeedが1の時を境に遷移するように設定します。

これでアニメーション遷移とその条件の設定が終わりました。この辺りは

Unityのアニメーションの切り替えシステムとスクリプト
Unityのアニメーションの切り替えシステムであるAnimatorControllerの設定とスクリプトからアニメーションを制御していきます。

の記事でやったのでそちらを参考にしてください。

敵キャラを動かす方法を考える

それではスクリプトを作成し敵キャラを移動させます。

敵キャラの場合は主人公キャラと違ってキーを押したら動くわけではないので、目的地を設定しそこに移動するようにします。

移動が終わったら次の目的地を設定し、また移動する。

という事を繰り返します。

キャラクターの移動はCharacterControllerの機能を使い目的地に移動させます。

アニメーションの切り替えはAnimatorControllerのアニメーションパラメータを操作し切り替えるようにします。

アニメーションは移動している時は歩くアニメーション、目的地についたらその場でただ立っているアニメーションにします。

今回はゾンビの初期位置をx:17、y:0、z:18にして、ゾンビの目的地をx:25、y:0、z:25にします。

敵キャラを動かすスクリプトを作成する

AssetsフォルダのscriptフォルダにMoveEnemyという名前のスクリプトを作成します。

このMoveEnemyに敵キャラが動くスクリプトを書いていきます。

MoveEnemyスクリプトを敵キャラにドラッグ&ドロップするか、敵キャラのインスペクタ上でAdd Componentからスクリプトの追加をします。

MoveEnemyスクリプトに処理を書いていきます。

まずはフィールド宣言です。

enemyControllerはゾンビに取り付けたCharacterControllerを入れます。

animatorはゾンビのAnimatorを入れます。

destinationはゾンビの目的地を入れます。

walkSpeedはゾンビの歩行スピードを入れます。

velocityはゾンビの速度を入れます。

directionは目的地の方向を設定します。

ゲームオブジェクト開始時に様々な初期処理を実行しておきます。

最初に決めた通り、目的地destinationにnew Vector3 (25f, 0f, 25f)を設定します。

次は移動の処理です。

敵キャラが接地(地面の上にいる)していたらアニメーションパラメータのSpeedの値を2.0にしWalkアニメーションに切り替えます。

1.0より大きい値であればなんでもかまわないです。

ただ1.0だとWalk→Idleへの条件とも合致するせいか何も反応しなくなりました。

directionは移動する方向を入れるフィールドで、

(目的地 - 現在のキャラの位置).normalized

で目的地の方向ベクトルが計算出来ます。

.normalizedは正規化した値を出すので距離は最短で方向だけ(単位ベクトル)を取り出す事が出来ます。

この方向に歩くスピード値をかけて移動させていきます。

次にキャラクターを目的地の方向に向かせたいので、

とします。

transform.LookAtで指定した位置を向かせる事が出来るので、引数にVector3で向かせたい位置を指定しています。

xとzの値は目的地の値を指定し、yの値だけはキャラクターのy値を指定します。

yは上下方向なので目的地のy値(transform.position.y)を指定すると目的地が山の上にあると、キャラクターが上を向いて進んでいくということになってしまう為にY座標だけはゾンビと同じにしておきます。

これでキャラクターの方向を目的地の方向に向ける事が出来ました。

ちなみにDebug.LogはUnityのConsoleに変数の値がちゃんと入っているかどうか?
の確認に使う事が出来ます。

あとは重力分をVelocityに換算し、CharacterControllerの機能を使って移動させるだけです。

ここまでのソースコードは以下の通り

敵キャラ移動スクリプトの問題点

ではUnityの実行ボタンを押して確認してみます。

移動は出来ましたが、目的地に到着しても目的地あたりでうごめくのがわかるかと思います。

敵6

到着しても知らせる処理を設けておらず、永遠に目的地に移動しようとしてしまいます。
本来であれば到着したらその場でIdleのアニメーションになりただ立っている状態にしたいところです。

敵キャラが目的地についたかどうかの情報を持たせる

それでは目的地に到着した場合、到着した!というフラグ(旗)を立て、その後は移動しないようにします。

新しいフィールドを宣言します。

到着したかどうかの判定に使うbool型のフィールドarrivedを宣言します。

bool型は真か偽かの判定に使うものです。

Startメソッド内で初期値としてfalseを入れておきます。最初はもちろん到着してませんからね。

さて次は到着したかどうかの判定部分です。到着したかどうかの判定は目的地と現在地の距離がかなり狭まった時に到着と判定する事にします。
2地点の距離はVector3.Distanceで求められるので、

距離が0.5未満になったら到着判定変数にtrueを入れ、アニメーターのSpeed値に0を入れます。

これで到着した場合の処理が完成しました。

高低差を考慮しない場合は

のようにY軸をゾンビと合わせます。

到着していた場合はキャラクターの移動はさせないように、到着していない場合のみ移動処理を実行させます。

ここまでの処理を追加したソースコードは以下の通りです。

arrivedがtrueになっていない時だけ処理をします。

これで指定した位置に敵キャラが移動するようになりました。

しかし、このスクリプトではいちいち目的地を設定し直さないといけなくなってしまい使い勝手がよくありません。

なのでnew Vector3(25f, 0f, 25f)としている場所をランダムに設定出来るようにしてみます。

目的地をランダムに設定出来るようにする

スタート位置(敵キャラを最初に置いた場所)から一定の範囲内にランダムに目的地を設定する事が出来るようにします。

最初にスタート位置を記憶しておきます。

スタート位置フィールドはstartPositionとし、Startメソッド内で初期位置を入れておきます。

Startメソッドはオブジェクトが現れた時に1回(厳密にはアクティブになった時1回)実行されるので、その時のオブジェクトの位置、つまりシーンに配置した位置(transform.position)を入れておきます。

次にランダム値を作ります。

Random.insideUnitCircleで半径1以内のVector2のランダムな点を作成する事が出来るので、半径8以内であれば、

となります。スタートポイントにランダムな点を足せば決められた範囲内で目的地を作る事が出来ます。

ランダムな点はVector2の点で得られるので、それをVector3に適用します。
Unityではyは上下、zは前後の動きなので、Vector2のy値をzに指定します。

Random.insideUnitCircleを使わずともランダム値を得るRandom.range(0.0f, 8.0f)を使って二つの値を作り、それを設定する事でも同じような結果が得られます。

以下全文です。

出来上がったので、Unityの実行ボタンを押して確認してみましょう。

ゾンビが目的地に移動し、目的地近くになったらその場でただ立っている状態になります。

敵7

終わりに

敵キャラが登場したら登場した位置を基点にランダムな目的地に移動するキャラクターが出来ました。

次回は目的地に移動したら数秒待機し別の目的地を設定し移動を開始するスクリプトを組みます。
諸事情によりスクリプトを分ける作業が入ります。

コメント

  1. 未来 より:

    MoveEnemyスクリプトのwalkSpeedが0になっていました。
    ありがとうございました。

  2. 未来 より:

    ゾンビが移動しません。

    コードをコピペしても、だめでした。

    • アニメーションをしているという事はAnimatorControllerの方は問題なさそうですね。

      ゾンビが移動しない理由があるとすればCharacterControllerコンポーネントを敵に設定していない。
      MoveEnemyスクリプトを敵に設定していない。
      MoveEnemyスクリプトではCharacterControllerコンポーネントのisGroundedプロパティで地面と接地していると判断した時だけ移動させるようにしているので、地面に接地出来ていない(敵を地面より少し上に移動してみてください)。
      敵キャラクターのインスペクタでMoveEnemyスクリプトのwalkSpeedが0になっている。
      MoveEnemyスクリプトの名前の横のチェックを外し非アクティブにしている。

      等の可能性が考えられます。

      また、コンソールに何らかのエラーが出ていないかどうかも確認してみてください。

      この記事の機能を再度作成してみましたが、わたくしの方では移動出来ているので、そこら辺を確認してみてください。

タイトルとURLをコピーしました