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);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章