[2025_12_03]Flocking(Boids)알고리즘

2025. 12. 3. 22:20TIL

현재 문제 상황

Project AM에서 유닛들이 이동할 때 다음과 같은 문제가 발생하고 있다:

  1. 유닛이 서로의 길을 막는 현상
    • 앞 유닛이 멈춰있으면 뒤 유닛도 같이 멈춰버림
    • 공간이 충분한데도 우회하지 못하고 그냥 대기함
  2. 비효율적인 이동 패턴
    • 여러 유닛이 같은 목표지점으로 이동할 때 병목 현상 발생
    • 유닛들이 겹치거나 한 곳에 뭉쳐서 움직임
  3. 부자연스러운 집단 행동
    • 실제 생명체처럼 자연스럽게 흩어지고 모이는 행동이 없음
    • 로봇처럼 딱딱하게 움직임

이 문제를 Flocking(Boids) 알고리즘으로 해결하고자 공부를 시작했다.

 

Flocking(Boids) 알고리즘이란?

Craig Reynolds가 1986년에 개발한 알고리즘으로, 새 떼(flock), 물고기 떼 같은 집단의 자연스러운 움직임을 시뮬레이션하는 방법이다.

각 개체(Boid)는 주변 이웃들을 관찰하고 세 가지 단순한 규칙만으로 복잡한 집단 행동을 만들어낸다. 중앙 통제 없이 각자가 독립적으로 판단하지만, 전체적으로는 마치 하나의 의지를 가진 것처럼 움직이는 게 핵심이다.


Flocking의 3가지 핵심 규칙

  1. Separation (분리)

목적: 다른 유닛과 충돌 방지 행동: 너무 가까운 이웃으로부터 멀어지려는 힘 효과: 유닛끼리 겹치지 않고, 개인 공간 확보

구현 아이디어

  • 일정 반경 내의 이웃들을 검색
  • 각 이웃으로부터 멀어지는 방향 벡터 계산
  • 거리에 반비례하는 힘 적용 (가까울수록 강한 회피력)
  • 모든 회피 벡터의 평균을 최종 분리 힘으로 사용
  1. Alignment (정렬)

목적: 주변과 같은 방향으로 이동 행동: 이웃들의 평균 속도를 따라감 효과: 집단이 일관된 방향으로 움직임

구현 아이디어

  • 일정 반경 내 이웃들의 속도 벡터 수집
  • 평균 속도 계산
  • 자신의 속도를 평균 속도 방향으로 조정
  • 무리가 같은 방향으로 흐르듯 이동
  1. Cohesion (응집)

목적: 그룹을 유지 행동: 주변 이웃들의 중심점을 향해 이동 효과: 유닛들이 흩어지지 않고 무리를 형성

구현 아이디어:

  • 일정 반경 내 이웃들의 위치 평균 계산 (무게중심)
  • 무게중심을 향하는 방향 벡터 계산
  • 중심을 향해 천천히 이동
  • 그룹이 완전히 흩어지지 않도록 유지

Unity 구현 기본 구조

FlockingUnit 클래스를 만들고 다음과 같이 구성:

주요 변수:

  • separationRadius, alignmentRadius, cohesionRadius: 각 규칙의 영향 범위
  • separationWeight, alignmentWeight, cohesionWeight: 각 규칙의 강도
  • maxSpeed: 최대 이동 속도
  • maxForce: 최대 가속력
  • velocity: 현재 속도 벡터
  • neighbors: 주변 이웃 유닛 리스트

매 프레임 실행 순서:

  1. FindNeighbors() - 주변 유닛 탐색
  2. CalculateFlockingForce() - 세 가지 규칙 계산하고 합산
  3. ApplyForce() - 계산된 힘을 속도에 적용
  4. Move() - 속도에 따라 실제 이동

핵심은 세 가지 규칙에서 나온 벡터를 가중치를 곱해서 합치고, 그 결과를 속도에 더하는 것이다.


가중치 조정 팁

상황별로 가중치를 다르게 설정하면 다양한 행동 패턴 구현 가능:

전투 중:

  • Separation: 높게 (2.0) - 넓게 퍼져서 공격
  • Alignment: 보통 (0.8) - 방향은 어느정도 맞춤
  • Cohesion: 낮게 (0.5) - 뭉치지 않음

이동 중:

  • Separation: 보통 (1.0) - 적당한 간격
  • Alignment: 높게 (1.5) - 같은 방향으로
  • Cohesion: 높게 (1.5) - 무리 유지

대기 중:

  • Separation: 높게 (2.0) - 서로 안 겹침
  • Alignment: 낮게 (0.3) - 각자 자유롭게
  • Cohesion: 보통 (1.0) - 흩어지지는 않음

이런 식으로 상황에 따라 SetCombatMode(), SetMoveMode() 같은 메서드로 가중치를 바꿔주면 된다.


다음 학습 계획

  1. NavMesh와 Flocking 통합
    • NavMesh로 기본 경로 찾기 (큰 장애물 회피)
    • Flocking으로 유닛 간 충돌 회피 및 자연스러운 움직임
    • 두 시스템의 장점을 합치기
  2. 장애물 회피 추가
    • Obstacle Avoidance 규칙 구현
    • 벽이나 지형지물을 감지해서 피하기
    • Raycast로 전방 체크
  3. 성능 프로파일링
    • Job System / Burst Compiler 적용 검토
    • 실제 게임에서 쓸 수 있는 수준으로 최적화

핵심 정리

오늘 배운 Flocking 알고리즘의 핵심:

Flocking = Separation + Alignment + Cohesion

각 유닛이 주변만 보고 독립적으로 판단하지만, 전체적으로는 지능적인 집단 행동을 만들어낸다. 중앙 통제 없이도 복잡한 패턴이 나온다는 게 신기하다.

가중치 조절로 다양한 행동 패턴 구현이 가능하고, 상황에 맞게 동적으로 바꿀 수 있다는 점이 매력적이다.

최적화는 필수다: 공간 분할, 업데이트 빈도 조절, 검색 반경 최적화를 꼭 해야 한다.

Project AM의 유닛 막힘 문제를 자연스럽고 효율적으로 해결할 수 있을 것 같다! 다음 주에 실제로 구현해봐야겠다.


참고 자료

  • Craig Reynolds - Boids (Original Paper): http://www.red3d.com/cwr/boids/
  • Sebastian Lague의 Coding Adventure: Boids 유튜브 영상 (시각적으로 이해하기 좋음)
  • Unity 공식 문서 및 커뮤니티 예제들