(この記事の使用環境: Unity5.4.2f2 Personal、Windows10


今回はNavMeshAgentを使ってみた話。

この前の記事
でゾンビをアニメーションさせましたが、プレイヤーに向かってくる際の移動と転回の処理はスクリプトリファレンスとにらめっこしながらがんばって書いたものです。
それがものすごくシンプルになります。

コードはこんな感じ。

using UnityEngine;
using System.Collections;

public class ZombieControllerByNav : MonoBehaviour
{
    public Transform target;

    public int lifeMax;
    int _currentlife;

    public float knockBack;

    NavMeshAgent nav;               // 追記

    // public float moveSpeed;     // いらなくなった
    // public float rotateSpeed;   // いらなくなった
    // Vector3 _relativePos;       // いらなくなった
    // Quaternion _rotation;       // いらなくなった

    Rigidbody rb;
    Animator anim;

    enum eState
    {
        Walk,
        Attack,
        Dead,
    }
    eState _state = eState.Walk;

    private void Start ()
    {
        rb = GetComponent<Rigidbody> ();
        anim = GetComponent<Animator> ();
        _currentlife = lifeMax;

        nav = GetComponent<NavMeshAgent> ();        // 追記
    }

    private void FixedUpdate ()
    {
        if (_state == eState.Walk)
        {
            nav.SetDestination (target.position);   // 追記
            nav.speed = 1.0f;                       // 追記

            /*
             *  ごっそりいらなくなった
             * 
            _relativePos = new Vector3 (target.position.x, 0, target.position.z) - transform.position;
            _rotation = Quaternion.LookRotation (_relativePos);
            rb.rotation = Quaternion.Lerp (transform.rotation, _rotation, rotateSpeed * Time.deltaTime);
            rb.MovePosition (transform.position + transform.forward * moveSpeed * Time.deltaTime);
            */
        }
    }

これならいちいちリファレンスを引かなくても書けそうです。

動作も問題ありません。


移動速度や転回速度などなどはインスペクタから設定できます。
全画面キャプチャ 20161225 235431

攻撃中は移動速度を遅くして、死んだら移動を止めていますが、その処理もラクチンです。

    private void OnTriggerEnter (Collider other)
    {
        if (other.tag == "Player")
        {
            anim.SetBool ("Attacking", true);
            _state = eState.Attack;
            nav.speed = 0.1f;                           // 追記(攻撃中は移動速度を遅くする)
        }

        if (other.tag == "Bullet" && _state != eState.Dead)
        {
            _currentlife--;
            Destroy (other.gameObject);
            Debug.Log ("Zombie Life: " + _currentlife);

            rb.AddForce (-transform.forward * knockBack);

            if (_currentlife <= 0)
            {
                anim.SetTrigger ("Died");
                _state = eState.Dead;
                rb.isKinematic = true;
                nav.Stop ();                            // 追記(死んだらNavMeshAgentを止める)
            }
        }
    }

    private void OnTriggerExit (Collider other)
    {
        if (other.tag == "Player")
        {
            anim.SetBool ("Attacking", false);
            _state = eState.Walk;
        }
    }
}

今回は以上です。