Unity AI行为之群组行为CraigReynold算法
发表于2018-09-30
public class FlockController : MonoBehaviour { public float minVelocity = 1; public float maxVeclocity = 8; public int flockSize = 20; public float centerWeight = 1; public float velocityWeight = 1; public float separationWeight = 1; public float followWeight = 1; public float randomizeWeight = 1; public Flock perfab; public Transform target; public Vector3 flockCenter; public Vector3 flockVelocity; public ArrayList flockList = new ArrayList(); void Start () { for(int i = 0; i < flockSize; i++) { Flock flock = Instantiate(perfab,transform.position,transform.rotation) as Flock; flock.transform.parent = transform; flock.controller = this; flockList.Add(flock); } } /* 先声明实现群组算法所需的所有属性,再基于输入的群组大小生成boid对象,和上次一样, */ void Update () { Vector3 center = Vector3.zero; Vector3 velocity = Vector3.zero; foreach(Flock flock in flockList) { center += flock.transform.localPosition; velocity += flock.transform.GetComponent<Rigidbody>().velocity; } flockCenter = center / flockSize; flockVelocity = velocity / flockSize; } /* 在Update方法中,保持更新群组的平均中心和速度,这些值来自于我们的boid对象,它们可以用来调整与控制者的凝聚与队列属性 */ }
下面是具有TargetMoement脚本的Target实体,稍后我们将创建这个脚本,我们选择一个附近的随机的目标点,并向其移动。当我们到达该点附近时,再选择一个新的点。这时所有boid都将跟随这个目标。
public class TargetMovement : MonoBehaviour { public Vector3 bound; public float speed = 100.0f; private Vector3 initialPosition; private Vector3 nextMovementPoint; void Start () { initialPosition = transform.position; CalculateNextMovementPoint(); } void CalculateNextMovementPoint() { float posX = Random.Range(initialPosition.x - bound.x,initialPosition.x + bound.x); float posY = Random.Range(initialPosition.y - bound.y,initialPosition.y + bound.y); float posZ = Random.Range(initialPosition.z - bound.z,initialPosition.z + bound.z); nextMovementPoint = initialPosition + new Vector3(posX,posY,posZ); } void Update () { transform.Translate(Vector3.forward * speed * Time.deltaTime); transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(nextMovementPoint - transform.position),1.0f * Time.deltaTime); if(Vector3.Distance(nextMovementPoint,transform.position)<=10.0f) { CalculateNextMovementPoint(); } } }
public class Flock : MonoBehaviour { public FlockController controller; private Rigidbody rigidbody; private void Awake() { rigidbody = transform.GetComponent<Rigidbody>(); } private void Start() { controller = transform.parent.GetComponent<FlockController>(); } private void Update() { if(controller) { Vector3 relativePos = steer() * Time.deltaTime; if(relativePos != Vector3.zero) { rigidbody.velocity = relativePos; } float speed = rigidbody.velocity.magnitude; if(speed > controller.maxVeclocity) { rigidbody.velocity = rigidbody.velocity.normalized * controller.maxVeclocity; }else if(speed < controller.minVelocity) { rigidbody.velocity = rigidbody.velocity.normalized * controller.minVelocity; } } } private Vector3 steer() { Vector3 center = controller.flockCenter - transform.localPosition; Vector3 velocity = controller.flockVelocity - rigidbody.velocity; Vector3 follow = controller.target.localPosition - transform.localPosition; Vector3 separation = Vector3.zero; foreach(Flock flock in controller.flockList) { if(flock != this) { Vector3 ralativePos = transform.localPosition - flock.transform.localPosition; separation += ralativePos / (ralativePos.sqrMagnitude); } } Vector3 randomize = new Vector3((Random.value * 2) - 1,(Random.value * 2) - 1,(Random.value * 2) - 1); randomize.Normalize(); return (controller.centerWeight * center + controller.velocityWeight * velocity + controller.separationWeight * separation + controller.followWeight * follow + controller.randomizeWeight * randomize); } }
来自:https://blog.csdn.net/qq_27880427/article/details/72771636