走っているプレイヤーに気づいて、敵が追ってくるようにしてみました。
プレイヤーが走っているとゲージが上がっていって、満タンになると敵がプレイヤーを追尾し初めます。プレイヤーが走っていないときはゲージが下がっていって、ゲージが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で途切れ方を変えられます。