Unity AI行为之群组行为CraigReynold算法

发表于2018-09-30
评论0 2.5k浏览
上篇文章中给大家介绍了群组行为的算法,这篇是替换实现,更加清晰。

FlockController的行为很简单,它在运行时生成boid的行为,更新群组的中心及群组的平均速度
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

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: