【Unity】敵が走っているプレイヤーに気づいて追尾する

投稿者: | 2020-10-10

走っているプレイヤーに気づいて、敵が追ってくるようにしてみました。

プレイヤーが走っているとゲージが上がっていって、満タンになると敵がプレイヤーを追尾し初めます。プレイヤーが走っていないときはゲージが下がっていって、ゲージが0になると追尾をやめます。

敵にプレイヤーが見えているかは一旦考えないでおきます。

プレイヤーを追っていないときは、敵にマップを巡回させます。そのための目的地をシリンダーで作ってマップ上に適当に配置し、空のゲームオブジェクトにまとめておきました。

敵に付けるスクリプトには、このルートのオブジェクトをアタッチします。

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AI;


public class AgentScript3 : MonoBehaviour
{
    [SerializeField] UnityStandardAssets.Characters.FirstPerson.FirstPersonController sc_fps;
    [SerializeField] Transform points;
    [SerializeField] Image gauge;
    [SerializeField] Text text;

    bool isChasing;
    Transform player;
    NavMeshAgent agent;
    float attention;

    // Start is called before the first frame update
    void Start()
    {
        player = sc_fps.transform;
        agent = GetComponent<NavMeshAgent>();
        agent.destination = GetDestinationRandomly();
        gauge.fillAmount = 0f;
    }

    // Update is called once per frame
    void Update()
    {
        // プレイヤーが走っていないとき
        if (sc_fps.GetIsWalking())
        {
            text.text = "P:走っていない";
            attention -= 0.003f; // 注意のレベルを下げる

            // 0以下のとき追っていない状態にする
            if (attention <= 0f)
            {
                attention = 0f;

                // 追っている状態から切り替わった時
                if(isChasing)
                {
                    agent.destination = GetDestinationRandomly(); // 次の巡回目標を設定
                }
                isChasing = false;
            }
        }
        // プレイヤーが走っているとき
        else {
            text.text = "P:走っている";
            attention += 0.005f; // 注意のレベルを上げる

            // 1以上のとき追っている状態にする
            if (attention >= 1f)
            {
                attention = 1f;                
                isChasing = true;
            }
        }

        if (isChasing)
        {
            text.text += "\nA:追っている";
            agent.destination = player.position; // プレイヤーの場所に行く
        }
        else
        {
            text.text += "\nA:追っていない";

            // 目的地についた時
            if (!agent.pathPending && agent.remainingDistance < 0.5f)
            {
                agent.destination = GetDestinationRandomly();
            }
        }

        gauge.fillAmount = attention; // ゲージに反映
    }

    // ランダムで目的地を返す
    Vector3 GetDestinationRandomly()
    {
        return points.GetChild(Random.Range(0, points.childCount)).transform.position;
    }
}

まずFirstPersonControllerに新しいメソッドを作って、プレイヤーが走っているかどうかを調べられるようにします。

// FirstPersonController
public bool GetIsWalking()
{
    return m_IsWalking;
}

シフトキーを押しているときはfalseが返って、押していないときはtrueが返ります。シフトキーを押しながら移動するとプレイヤーは走りますが、そのときに移動キーを押さなければプレイヤーは立ち止まったままfalseが返るので修正がいるかもしれません。

エージェントのスクリプトからこのメソッドを呼びます。プレイヤーが走っていないときは、注意のレベルを下げていき、0以下のとき0にして、プレイヤーを追っていない状態にします。

追っている状態から切り替わったときは、巡回のための次の目的地をランダムに設定します。

// プレイヤーが走っていないとき
if (sc_fps.GetIsWalking())
{
    text.text = "P:走っていない";
    attention -= 0.003f; // 注意のレベルを下げる

    // 0以下のとき追っていない状態にする
    if (attention <= 0f)
    {
        attention = 0f;

        // 追っている状態から切り替わった時
        if(isChasing)
        {
            agent.destination = GetDestinationRandomly(); // 次の巡回目標を設定
        }
        isChasing = false;
    }
}

走っているときは、注意のレベルを上げていき、1以上になると1にして追っている状態にします。

// プレイヤーが走っているとき
else {
    text.text = "P:走っている";
    attention += 0.005f; // 注意のレベルを上げる

    // 1以上のとき追っている状態にする
    if (attention >= 1f)
    {
        attention = 1f;                
        isChasing = true;
    }
}

そして、追っているときはプレイヤーの位置を目的地にセットして、追っていないときは、巡回の目的地に近づいたときに次の目的地をセットします。最後に注意のレベルをゲージに反映しています。

if (isChasing)
{
    text.text += "\nA:追っている";
    agent.destination = player.position; // プレイヤーの場所に行く
}
else
{
    text.text += "\nA:追っていない";

    // 目的地についた時
    if (!agent.pathPending && agent.remainingDistance < 0.5f)
    {
        agent.destination = GetDestinationRandomly();
    }
}

gauge.fillAmount = attention; // ゲージに反映

このままだと、ゲージが0にならないと追うのをやめないので、逃げるのが難しすぎるかもしれません。

ゲージのためのImageオブジェクトでは、ImageコンポーネントのSource Imageに真っ白いスプライトをアタッチしてColorで色を調節し、Image TypeをFilledにして、Fill Amountの値で画像が途切れるようにしています。

Fill MethodとFill Originで途切れ方を変えられます。

コメントを残す

メールアドレスが公開されることはありません。