AI_群组行为

using System.Collections.Generic;
using UnityEngine;

public class CrowAI : MonoBehaviour {
    //当前速度 
    public float speed = 10;
    public Vector3 velocity = Vector3.forward;
    private Vector3 startVelocity;//初始化当前速度
    public Transform target;//目标点
    //总力
    public Vector3 sumForce = Vector3.zero;
    //质量
    public float m = 3;

    //分离的力
    public float sparationDistance = 3;   //分离的距离
    public List<GameObject> sparationNeighbors = new List<GameObject>();
    public float sparationWeight = 1; //权重
    public Vector3 sparationForce = Vector3.zero;

    //队列的力
    public float alignmentDistance = 4;
    public List<GameObject> alignmentNeighbors = new List<GameObject>();
    public float alignmentWeight = 1; //权重
    public Vector3 alignmentForce = Vector3.zero;

    //聚集的力
    public float cohesionWeight = 3;//权重
    public Vector3 cohesionForce = Vector3.zero;
    //间隔几秒检测一次
    public float checkInterval = 0.2f;

    private Animation anim;
    public float animRandom = 2;
    void Start()
    {
        target = GameObject.Find("target").transform;
        startVelocity = velocity;
        //0 秒后调用 CalcForce() 方法,并且之后每隔 checkInterval 秒调用一次 CalcForce() 方法
        InvokeRepeating("CalcForce", 0, checkInterval);
        anim = GetComponentInChildren<Animation>();
        Invoke("Playanim", Random.Range(0, animRandom));
    }
    void Playanim() {
        anim.Play();
    }

    void CalcForce() {
        //计算之前先归零
        sumForce = Vector3.zero;
        sparationForce = Vector3.zero;
        alignmentForce = Vector3.zero;
        cohesionForce = Vector3.zero;

        //先清空集合
        sparationNeighbors.Clear();
        Collider[] colliders = Physics.OverlapSphere(transform.position, sparationDistance);
        foreach (Collider c in colliders)
        {
            //判断该物体近的邻居
            if (c!=null && c.gameObject!=this.gameObject)
            {
                sparationNeighbors.Add(c.gameObject);
            }
        }

        //1.计算分离的力
        foreach (GameObject neighbor in sparationNeighbors)
        {
            Vector3 dir = transform.position - neighbor.transform.position;
            sparationForce += dir.normalized / dir.magnitude;
        }
        //如果附近有物体
        if (sparationNeighbors.Count > 0)
        {
            //得到分离的力
            sparationForce *= sparationWeight;
            //得到的力赋值给总力
            sumForce += sparationForce;
        }

        //2.计算队列的力(整体一个前进的力)
        alignmentNeighbors.Clear();
        colliders = Physics.OverlapSphere(transform.position, alignmentDistance);
        foreach (Collider c in colliders)
        {
            if (c!=null &&c.gameObject !=this.gameObject)
            {
                alignmentNeighbors.Add(c.gameObject);
            }
        }
        //计算邻居的平均朝向
        Vector3 avgDir = Vector3.zero;
        //朝向的总和
        foreach (GameObject n in alignmentNeighbors)
        {
            avgDir += n.transform.forward;
        }
        if (alignmentNeighbors.Count >0)
        {
            //得到平均数
            avgDir /= alignmentNeighbors.Count;
            //得到相对方向
            alignmentForce = avgDir = transform.forward;
            alignmentForce *= alignmentWeight;
            //得到的力赋值给总力
            sumForce += alignmentForce;
        }

        //3.聚集的力
        if (alignmentNeighbors.Count > 0)
        {
            Vector3 center = Vector3.zero;
            foreach (GameObject n in alignmentNeighbors)
            {
                center += n.transform.position;
            }
            center /= alignmentNeighbors.Count;
            Vector3 dirToCenter = center - transform.position;
            cohesionForce += dirToCenter.normalized * velocity.magnitude;
            cohesionForce *= cohesionWeight;
            sumForce += cohesionForce;
        }

        //4.保持恒定飞行速度的力
        Vector3 enginForce = velocity.normalized * startVelocity.magnitude;
        sumForce += enginForce * 0.1f;
        //4.保持恒定目标飞行的效果
        Vector3 targetDir = target.position - transform.position;
        sumForce += (targetDir.normalized - transform.forward)*speed;
    }


    void Update () {
        //加速度(根据牛顿第二定律)
        Vector3 a = sumForce / m;
        //计算出速度
        velocity += a * Time.deltaTime;
        //物体运行
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(velocity), Time.deltaTime*3);
        transform.Translate(transform.forward * Time.deltaTime * velocity .magnitude, Space.World);
    }
}

 

posted @ 2018-03-21 17:31  一只默默奮鬥的程序菌  阅读(398)  评论(0编辑  收藏  举报