KITASENJU DESIGN BLOG

memo, html, javascript, unity

simple boids with c#

// 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;

    }

}
"FOOTER"