// based https://p5js.org/examples/simulate-flocking.html using System.Collections; using System.Collections.Generic; using UnityEngine; public class Boids : MonoBehaviour { [SerializeField] private int NUM = 100; [SerializeField] BoidsPiece _prefab; [SerializeField] List<BoidsPiece> _pieces; [SerializeField] private float _maxSpeed = 3f; [SerializeField] private float _maxForce = 0.05f; [Header("各パラメータ")] [SerializeField] private float _spdSep = 1f; [SerializeField] private float _spdAlign = 1f; [SerializeField] private float _spdCohe = 1f; [Header("各areaパラメータ")] [SerializeField] private float _distSep = 1f; [SerializeField] private float _distAlign = 1f; [SerializeField] private float _distCohe = 1f; //[SerializeField] private Vector3 _dir; // Start is called before the first frame update void Start() { _pieces = new List<BoidsPiece>(); for(int i=0;i<NUM;i++){ var g = Instantiate(_prefab,transform,false); _pieces.Add(g); g.transform.localPosition = new Vector3( Random.value-0.5f, Random.value-0.5f, Random.value-0.5f ); } _prefab.gameObject.SetActive(false); } //https://p5js.org/examples/simulate-flocking.html // Update is called once per frame void Update() { for(int i=0;i<_pieces.Count;i++){ int countSep = 0; int countAlign = 0; int countCohe = 0; var steerSep = Vector3.zero; var steerAlign = Vector3.zero; var sumCohe = Vector3.zero; var me = _pieces[i]; for(int j=0;j<_pieces.Count;j++){ if(i==j) continue; var you = _pieces[j]; var dist = Vector3.Distance( me.transform.localPosition, you.transform.localPosition ); //=====separation //ある距離より離れていたら反発する if ((dist > 0) && (dist < _distSep)) { // Calculate vector pointing away from neighbor var diff = me.transform.localPosition - you.transform.localPosition; if(diff.sqrMagnitude>0){ diff.Normalize(); diff = diff / dist; // Weight by distance steerSep += diff; countSep++; // Keep track of how many } } //let sep = this.separate(boids); // Separation //let ali = this.align(boids); // Alignment //let coh = this.cohesion(boids); // Cohesion //=====Align //同じ方向に進む if ((dist > 0) && (dist < _distAlign)) { steerAlign += you.velocity; countAlign++; } //=====Cohesion //群れの中心に向かう if ((dist > 0) && (dist < _distCohe)) { sumCohe += you.transform.localPosition; // Add location countCohe++; } } if(countSep>0){ me.velocity += steerSep/countSep * _spdSep; } if(countAlign>0){ me.velocity += steerAlign/countAlign * _spdAlign; } if(countCohe>0){ var center = sumCohe/countCohe; var centerV = center-me.transform.localPosition; centerV.Normalize(); centerV = centerV * _maxSpeed; var steer = centerV - me.velocity; centerV = Vector3.ClampMagnitude(steer,_maxForce); me.velocity += centerV * _spdCohe; } me.velocity = Vector3.ClampMagnitude( me.velocity, this._maxSpeed ); me.transform.localPosition += me.velocity; var pos = me.transform.localPosition; var lim = 5f; if(pos.x < -lim){pos.x = lim; Reset(me.transform);} if(pos.x > lim){pos.x = -lim; Reset(me.transform);} if(pos.y < -lim){pos.y = lim; Reset(me.transform);} if(pos.y > lim){pos.y = -lim; Reset(me.transform);} if(pos.z < -lim){pos.z = lim; Reset(me.transform);} if(pos.z > lim){pos.z = -lim; Reset(me.transform);} //me.transform.localPosition=pos; var tgtQ = Quaternion.LookRotation(me.velocity,Vector3.up); me.transform.rotation = Quaternion.Lerp(me.transform.rotation, tgtQ, 0.05f); } } void Reset(Transform tt){ tt.localPosition = Vector3.zero; } }