範囲内で追いかける
CoddyのUnityジャーニー「物理演算とゲームプレイ」セクションの一部。レッスン 53/71。
ほとんどの敵は、近づくまでは何もしてきません。物理演算の各ステップでプレイヤーとの距離を測り、一定の範囲内にいるときだけ追いかけます。このスライムはsightRangeの範囲内で追いかけ、その外では停止します。
void FixedUpdate()
{
Vector3 toPlayer = player.position - rb.position;
toPlayer.y = 0f;
if (toPlayer.magnitude < sightRange)
{
Vector3 dir = toPlayer.normalized;
rb.linearVelocity = new Vector3(dir.x * speed, rb.linearVelocity.y, dir.z * speed);
}
else
{
rb.linearVelocity = new Vector3(0f, rb.linearVelocity.y, 0f);
}
}elseが重要です。Rigidbodyは、何かが変えるまで速度を保ちます。これがないと、プレイヤーを見失ったスライムは摩擦で止まるまで滑り続け、氷の上では決して止まりません。最初にyを0に設定しているので、toPlayer.magnitudeは地面に沿った距離になります。そのため、スライムの隣にある木箱の上に立っているプレイヤーも、隣にいると判定されます。
範囲を1つだけにすると、弱点があります。その境界上に立っているプレイヤーは範囲内に入ったり出たりするため、スライムは何度も動き出したり止まったりします。敵は2つの範囲を使ってこれを防ぎます。短い範囲内でプレイヤーに気づき、より長い範囲の外に出たときだけ追跡をあきらめます。boolで敵が追跡中かどうかを記憶し、2つの範囲の間ではその状態が変わらないため、敵はそれまでの行動を続けます。
チャレンジ
中級オオカミが近くにいるプレイヤーに気づき、遠く離れると追跡をやめるようにします。
FixedUpdate()でプレイヤーまでの平面上の距離を求めます。距離がnoticeRange未満なら、bool chasingフィールドをtrueに設定し、giveUpRangeを超えたらfalseに設定します。chasing中は、yの値を維持しながら、プレイヤーに向かうようにrb.linearVelocityをspeedに設定します。- それ以外の場合は、
rb.linearVelocity = new Vector3(0f, rb.linearVelocity.y, 0f);に設定します。
「プレイ」を押し、オオカミに近づいてから走り去ります。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
public class Wolf : MonoBehaviour
{
[SerializeField] private Transform player;
[SerializeField] private float speed = 3f;
[SerializeField] private float noticeRange = 4f;
[SerializeField] private float giveUpRange = 8f;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
// プレイヤーを見つけるか、追跡を諦めるかを判断し、追いかけるかその場にとどまる
}
}
物理演算とゲームプレイのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド