AI-群组行为

不使用群组行为

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Crow : MonoBehaviour
{
    public float animRandom = 2f;

    public float speed = 1;
    public Transform target;
    //public Vector3 velocity = Vector3.forward;    //有target之后就不能使用了
    
    //取消Play Automatically
    private Animation animation;

    private IEnumerator Start()
    {
        //因为是场景中的物体所以无法拖拽apply
        target = GameObject.Find("Target").transform;
        animation = GetComponentInChildren<Animation>();
        yield return new WaitForSeconds(Random.Range(0, animRandom));
        animation.Play();
    }

    void Update ()
    {   //向前移动没有目标        
        //this.transform.Translate(velocity * Time.deltaTime, Space.World);	
        //有目标
        transform.LookAt(target.position);
        transform.Translate(Vector3.forward * Time.deltaTime * speed);
	}
}

使用群组行为实现分离,队列,聚散

牛顿第二定律:速度V,加速度a,质量m;第二定律:F=ma,a=F/m;F为受到的力;所以在程序中a=F;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CrowNew : MonoBehaviour
{
    private Vector3 startVelocity;               //初始速度
    private Vector3 velocity = Vector3.forward;  //速度
    private float m = 1;                         //质量

    //添加一个向量  合力
    private Vector3 sumForce = Vector3.zero;

    //分离力
    private Vector3 separationForce = Vector3.zero;              
    public float separationDistance = 3;          //分离的距离,3米以内的乌鸦将分离
    private List<GameObject> separationNeighbors = new List<GameObject>(); //存放得到的3米内的物体
    public float separationWeight = 1;            //分离力的权重


    //队列的力
    private Vector3 alignmentForce = Vector3.zero;
    public float alignmentDistance = 6;         //队列力的距离
    private List<GameObject> alignmentNeighbors = new List<GameObject>();
    public float alignmengWight = 1;


    //聚集的力
    private Vector3 cohesionForce = Vector3.zero;
    public float cohesionWight = 1;

    private float checkInterval = 0.2f;      //检查时间间隔

    private Animation ani;
    private float animRandom = 2f;

    #region 计算力的方法
    private void CalcForce()
    {
        sumForce = Vector3.zero;
        separationForce = Vector3.zero;
        alignmentForce = Vector3.zero;
        cohesionForce = Vector3.zero;

        #region 分离力
        separationNeighbors.Clear();
        //计算3米内有什么物体
        Collider[] colliders = Physics.OverlapSphere(this.transform.position, separationDistance); //以当前位置为中心,separationDistance为半径
        foreach (Collider c in colliders)
        {
            if (c!=null&&c.gameObject!=this.gameObject)     //不添加自身
            {
                separationNeighbors.Add(c.gameObject);
            }
        }
        //计算分离的力
        foreach (GameObject neighbor in separationNeighbors)
        {
            Vector3 dir = transform.position - neighbor.transform.position;//相反的方向
            separationForce += dir.normalized/dir.magnitude; //分离的力单位化除以dir的长度改变力的大小
        }
        if (separationNeighbors.Count>0)    //邻居不能为空,否则无限远离
        {
            separationForce *= separationWeight;
            sumForce += separationForce;
        }
        #endregion
        
        #region 队列的力
        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; //avgDir就是want方向-当前方向=alignmentForce,want与当前方向越近力越小
                alignmentForce *= alignmengWight;
                sumForce += alignmentForce;
            }            
        }
        #endregion

        #region 聚集的力

        if (separationNeighbors.Count<0||alignmentNeighbors.Count>0)
        {
            //计算中心点
            Vector3 center = Vector3.zero;
            foreach (GameObject item in alignmentNeighbors)
            {
                center += item.transform.position;
            }
            center /= alignmentNeighbors.Count;//得到中心点
            Vector3 dir2Center = center - transform.position;//施加力的方向
            cohesionForce += dir2Center;
            cohesionForce *= cohesionWight;
            sumForce += cohesionForce;
        }

        #endregion

        //保持恒定飞行速度的力
        Vector3 engineForce = startVelocity - velocity;//want方向-当前方向
        sumForce += engineForce * 0.3f;
    }
    #endregion

    private void Start()
    {
        startVelocity = velocity;
        InvokeRepeating("CalcForce", 0, checkInterval);
        ani = GetComponentInChildren<Animation>();
        Invoke("PlayAnim", Random.Range(0, animRandom));              
    }
   
    private void PlayAnim()
    {
        ani.Play();
        startVelocity = velocity;
    }

    private void Update()
    {
        Vector3 a = sumForce / m;   //加速度
        velocity += a * Time.deltaTime;
        //transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(velocity), Time.deltaTime); //自身的朝向就是飞行的方向
        transform.rotation =  Quaternion.LookRotation(velocity);
        transform.Translate(velocity * Time.deltaTime, Space.World);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42459006/article/details/83961941
今日推荐