Programming/algorithm
[Algorithm] Boids
devfactory
2024. 9. 28. 23:09
boids는 생물의 집단행동(새 무리의 이동 등)을 시뮬레이션 하는 알고리즘이다.
기본적으로 3개의 규칙을 따른다.
1. 응집(Cohesion): 주변 boid들과 평균위치를 향한다.
2. 분리(Separation): 주변 boid들과 충돌하지 않도록 방향을 돌린다.
3. 정렬(Alignment): 주변 boid들과 같은 방향을 향한다.
응집 - Cohesion
Boid는 주변의 Boid의 곁으로 가려는 성질이 있다.
주변 Boid의 위치의 평균을 구해 해당 방향으로 향한다.
Vector3 Cohesion(Transform[] _targets)
{
Vector3[] targets = Change(_targets, (Transform target) => target.position);
return Average(targets) - transform.position;
}
분리 - Separation
Boid는 다른 Boid와 너무 가까워 지지 않으려는 성질이 있다.
가까이 접근한 Boid들의 반대방향의 평균으로 향한다.
Boid의 거리에 비례해 가까이 있는 boid일수록 더 민감하게 반응하도록 하였다.
Vector3 Separation(Transform[] _targets)
{
Vector3[] targets = Change(_targets, (Transform target) => transform.position - target.position);
return Average(targets, (Vector3 vec) => vec.normalized * vec.magnitude / Boids.SeparationRadius);
}
정렬 - Alignment
Boid는 주변의 Boid와 같은 방향을 향하려는 성질이 있다.
주변의 Boid의 Vector의 평균방향을 향한다.
Vector3 Alignment(Transform[] _targets)
{
Vector3[] targets = Change(_targets, (Transform target) => target.forward);
return Average(targets);
}
위의 3가지 요소 외에도 장애물을 피하는 방향과 같이 다른 요소들을 추가 할 수 있다.
요소들의 값을 구하면 가중치를 곱한뒤 모든 요소의 합을 구해 해당방향을 바라보도록 천천히 회전시킨다.
void Update()
{
Transform[] targets = Change(Physics.OverlapSphere(transform.position, Boids.SeparationRadius), (Collider coll) => coll.transform);
if(targets.Length > Boids.maxNeighbourCount)
{
var t = new List<Transform>();
int count = 0;
for (int i = 0; i < targets.Length; i++)
{
t.Add(targets[i]);
}
targets = t.ToArray();
}
var SeparationVec = Separation(targets).normalized * Boids.SeparationWight;
Debug.DrawRay(transform.position, Separation(targets).normalized, Color.red);
targets = Change(Physics.OverlapSphere(transform.position, Boids.NeighbourRadius), (Collider coll) => coll.transform);
var AlignmentVec = Alignment(targets).normalized * Boids.AlignmentWight;
Debug.DrawRay(transform.position, Alignment(targets).normalized, Color.blue);
var CohesionVec = Cohesion(targets).normalized * Boids.CohesionWight;
Debug.DrawRay(transform.position, Cohesion(targets).normalized, Color.green);
var boundsVec = Bounds() * Boids.BoundsWight;
var obstacle = Obstacle().normalized * Boids.obstacleWight;
var LookVec = SeparationVec + AlignmentVec + CohesionVec + boundsVec + obstacle + RandomVec ;
if (!Boids.Space3D) LookVec.y = 0;
LookVec = Vector3.Lerp(transform.forward, LookVec, Time.deltaTime * Boids.RotateSpeed);
Quaternion targetQuaternion = Quaternion.LookRotation(LookVec);
transform.rotation = targetQuaternion;
}
전체 코드: https://github.com/dheiejsbd/Boids
GitHub - dheiejsbd/Boids
Contribute to dheiejsbd/Boids development by creating an account on GitHub.
github.com
반응형