上一節(jié)介紹了Seek以及Flee,和Seek相對(duì)應(yīng)的還有Arrival操控力行為
Arrival 和Seek的區(qū)別
Seek行為對(duì)于讓一個(gè)智能體向正確方向移動(dòng)很有用,但是很多情況是希望智能體能緩緩地停在目標(biāo)位置,而Seek行為是到達(dá)Target以后再其周圍來(lái)回?cái)[動(dòng)。
Arrive 行為是一種操控智能體慢慢減速直至停在目標(biāo)位置的行為。
Arrive原理(方案一)
Paste_Image.png
- 代碼實(shí)現(xiàn):
- 由于Arrive行為大致和Seek一致,于是我們?cè)赟eek的代碼上添加減速半徑slowDownRadius、物體與Target的距離distance。
Paste_Image.png
Paste_Image.png
距離:distance=toTarget.magnitude;
接著對(duì)距離進(jìn)行判斷,如果距離大于減速半徑說(shuō)明不需要減速,小于則需要減速。
Paste_Image.png
- 場(chǎng)景中的實(shí)現(xiàn)
- 設(shè)置最大速度,減速半徑,以及Target目標(biāo)點(diǎn)
Paste_Image.png
Paste_Image.png
- 方案二:
- 使用distance/slowdownRadius,從1-0變化的,且是線性變化,可以使得速度的改變是平滑的。
Paste_Image.png
- 場(chǎng)景演示:
Paste_Image.png
-
Arrival AI代碼:
public class Arrival : MonoBehaviour {
public float max_velocity; //游戲物體運(yùn)動(dòng)的最大速度
public Transform Target; //目標(biāo)物體的位置
public Vector3 velocity; //物體的速度public float slowDownRadius; //減速半徑 private float timer; //計(jì)時(shí)器 private List<Vector3> pathList; //繪制逃離路線 void Start() { max_velocity = 8; timer = 0; pathList = new List<Vector3>(); pathList.Add(transform.position); }
void Update()
{timer += Time.deltaTime; if (timer > 0.2f) { timer = 0; pathList.Add(transform.position); } //操控力的定義 Vector3 steeringForce = new Vector3(0, 0, 0); //首先要判斷他們之間的距離是否到了半徑之內(nèi) Vector3 toTarget = Target.position - this.transform.position; //之后求距離 float distance = toTarget.magnitude; ////第一種方案,漸漸的減速 //if (distance > slowDownRadius) //{ // //如果大于減速半徑就是Seek行為 // Vector3 desiredVelocity = (Target.position - transform.position).normalized * max_velocity; // //操控力 // steeringForce = desiredVelocity - velocity; //} //else //{ // //如果小于減速半徑就是Arrival行為 // Vector3 desiredVelocity = toTarget - velocity; // //操控力 // steeringForce = desiredVelocity - velocity; //} //第二種方案,突然的減速 if (distance > slowDownRadius) { //如果大于減速半徑就是Seek行為 Vector3 desiredVelocity = (Target.position - transform.position).normalized * max_velocity; //操控力 steeringForce = desiredVelocity - velocity; } else { //如果小于減速半徑就是Arrival行為,系數(shù)是(distance / slowDownRadius) Vector3 desiredVelocity = -toTarget.normalized * max_velocity * (distance / slowDownRadius); //操控力 steeringForce = desiredVelocity - velocity; } //加速度acc,速度除以質(zhì)量,這里質(zhì)量為1 Vector3 acc = steeringForce / 1; velocity += acc * Time.deltaTime; transform.position += velocity * Time.deltaTime; //如果速度的模大于0.01,說(shuō)明有速度,然后設(shè)置偏轉(zhuǎn),進(jìn)行弧線插值計(jì)算 if (velocity.magnitude > 0.01f) { //設(shè)置偏轉(zhuǎn),得到中間的插值,向前的力 Vector3 newForward = Vector3.Slerp(transform.forward, velocity, Time.deltaTime); newForward.y = 0; transform.forward = newForward; } for (int i = 0; i < pathList.Count - 1; i++) { Debug.DrawLine(pathList[i], pathList[i + 1], Color.red); }
}
}