NavMeshAgent
ステージの作成
1.CreateEmptyからStageを原点に作成する。
2.Stageの中にCubeからFloorを作成し表面材質を設定する。transformは以下
●Floor

3.Stageの中にCylinderを複数作成する。(複製しながら行うとよい)
●Cylinder

●Cylinder(1)

●Cylinder(2)

4.複製を繰り返し、下図のような感じにする。(だいたいでよい)

NavMeshの作成
敵の追跡ルートとなるNavMeshを作成する。
5.Stageの子要素をShiftキーを押しながらすべて選択する。

6.複数選択した状態でインスペクター右上隅にあるstaticからNavigation Staticを選択する。

7.Window->AI->Navigationを選択し、Bakeタブであることを確認し、下部のBakeボタンを押す。

8.下図のように探索できるルート(濃い青の部分)が焼き込まれる。
Playerの作成
9.CubeからPlayerを作成し、表面材質を設定する。transformは以下。

10.まずはもっとも単純に移動スクリプトを作るPlayerController1.csとして以下のように作成する。
01 | using System.Collections; |
02 | using System.Collections.Generic; |
05 | public class PlayerController1 : MonoBehaviour { |
08 | transform.Rotate ( 0 , Input.GetAxis ( "Horizontal" ), 0 ); |
09 | transform.Translate ( 0 , 0 ,Input.GetAxis ( "Vertical" ) * 5 .0f*Time.deltaTime); |
11.Playerに付与して実行してみよう。Translateでの移動は最強といっていい。あらゆるものを無視して移動する。当然Cylinderをすり抜ける。
Enemyの作成
12.それでは追跡してくる敵を作成しよう。CapsuleからEnemyを作成し表面材質を設定する。Transformは以下。

13.AddComponentからNavigation->Nav Mesh Agent を付与する。
14.EnemyController.csを以下のように作成して、Enemyに付与する。(using UnityEngin.AIを忘れないこと)
01 | using System.Collections; |
02 | using System.Collections.Generic; |
06 | public class EnemyController : MonoBehaviour |
08 | public Transform player; |
10 | public float traceDist = 10 .0f; |
15 | nav = GetComponent<NavMeshAgent>(); |
17 | StartCoroutine(CheckDist()); |
20 | IEnumerator CheckDist() |
25 | yield return new WaitForSeconds( 0 .2f); |
27 | float dist = Vector3.Distance(player.position, transform.position); |
32 | nav.SetDestination(player.position); |
15.インスペクターからplayerを登録し、実行してみよう。プレイヤーの距離に応じて追跡を開始すれば成功だ。
Playerの動き変更1
16.今のままではPlayerはステージ外にいっても落ちないし、Cylinderもすり抜ける。修正しよう。PlayerにCharacterControllerを付与する。
17.PlayerController1を無効にして、PlayerController2を以下のように作成し付与する。
01 | using System.Collections; |
02 | using System.Collections.Generic; |
05 | public class PlayerController2 : MonoBehaviour { |
06 | private CharacterController cc; |
08 | cc = GetComponent<CharacterController> (); |
11 | transform.Rotate(Vector3.up*Input.GetAxis( "Horizontal" )); |
12 | cc.Move (transform.forward*Input.GetAxis( "Vertical" )*Time.deltaTime* 5 .0f); |
18.Move関数で動かすことにより、Sylinderをすり抜けられなくなった。その他にも坂があれば45度以下は登るし、30cmの段差なら無視して進むことができる。ただ、Move関数は自分で重力を実装しないと下方向の重力はない。(ステージ外に行っても落ちない)
19.さらに変更してみよう。以下のようにMoveからSimpleMoveでの移動に変更してみる。
01 | using System.Collections; |
02 | using System.Collections.Generic; |
05 | public class PlayerController2 : MonoBehaviour { |
06 | private CharacterController cc; |
09 | cc = GetComponent<CharacterController> (); |
14 | transform.Rotate(Vector3.up*Input.GetAxis( "Horizontal" )); |
16 | cc.SimpleMove (transform.forward*Input.GetAxis( "Vertical" )*Time.deltaTime* 120 .0f); |
20.SimpleMoveでは重力が与えらる。なので画面外に行った時に落下する。しかもEnemyと衝突したときに押し出されることも確認できる。ただし、スクリプトによって上方にジャンプパワーなどを与えることはできない。MoveとSimpleMoveはどちらも癖がある、どちらを使うかは吟味のしどころだ。
コメント