2025. 12. 3. 22:20ㆍTIL
현재 문제 상황
Project AM에서 유닛들이 이동할 때 다음과 같은 문제가 발생하고 있다:
- 유닛이 서로의 길을 막는 현상
- 앞 유닛이 멈춰있으면 뒤 유닛도 같이 멈춰버림
- 공간이 충분한데도 우회하지 못하고 그냥 대기함
- 비효율적인 이동 패턴
- 여러 유닛이 같은 목표지점으로 이동할 때 병목 현상 발생
- 유닛들이 겹치거나 한 곳에 뭉쳐서 움직임
- 부자연스러운 집단 행동
- 실제 생명체처럼 자연스럽게 흩어지고 모이는 행동이 없음
- 로봇처럼 딱딱하게 움직임
이 문제를 Flocking(Boids) 알고리즘으로 해결하고자 공부를 시작했다.
Flocking(Boids) 알고리즘이란?
Craig Reynolds가 1986년에 개발한 알고리즘으로, 새 떼(flock), 물고기 떼 같은 집단의 자연스러운 움직임을 시뮬레이션하는 방법이다.
각 개체(Boid)는 주변 이웃들을 관찰하고 세 가지 단순한 규칙만으로 복잡한 집단 행동을 만들어낸다. 중앙 통제 없이 각자가 독립적으로 판단하지만, 전체적으로는 마치 하나의 의지를 가진 것처럼 움직이는 게 핵심이다.
Flocking의 3가지 핵심 규칙
- Separation (분리)
목적: 다른 유닛과 충돌 방지 행동: 너무 가까운 이웃으로부터 멀어지려는 힘 효과: 유닛끼리 겹치지 않고, 개인 공간 확보
구현 아이디어
- 일정 반경 내의 이웃들을 검색
- 각 이웃으로부터 멀어지는 방향 벡터 계산
- 거리에 반비례하는 힘 적용 (가까울수록 강한 회피력)
- 모든 회피 벡터의 평균을 최종 분리 힘으로 사용
- Alignment (정렬)
목적: 주변과 같은 방향으로 이동 행동: 이웃들의 평균 속도를 따라감 효과: 집단이 일관된 방향으로 움직임
구현 아이디어
- 일정 반경 내 이웃들의 속도 벡터 수집
- 평균 속도 계산
- 자신의 속도를 평균 속도 방향으로 조정
- 무리가 같은 방향으로 흐르듯 이동
- Cohesion (응집)
목적: 그룹을 유지 행동: 주변 이웃들의 중심점을 향해 이동 효과: 유닛들이 흩어지지 않고 무리를 형성
구현 아이디어:
- 일정 반경 내 이웃들의 위치 평균 계산 (무게중심)
- 무게중심을 향하는 방향 벡터 계산
- 중심을 향해 천천히 이동
- 그룹이 완전히 흩어지지 않도록 유지
Unity 구현 기본 구조
FlockingUnit 클래스를 만들고 다음과 같이 구성:
주요 변수:
- separationRadius, alignmentRadius, cohesionRadius: 각 규칙의 영향 범위
- separationWeight, alignmentWeight, cohesionWeight: 각 규칙의 강도
- maxSpeed: 최대 이동 속도
- maxForce: 최대 가속력
- velocity: 현재 속도 벡터
- neighbors: 주변 이웃 유닛 리스트
매 프레임 실행 순서:
- FindNeighbors() - 주변 유닛 탐색
- CalculateFlockingForce() - 세 가지 규칙 계산하고 합산
- ApplyForce() - 계산된 힘을 속도에 적용
- 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() 같은 메서드로 가중치를 바꿔주면 된다.
다음 학습 계획
- NavMesh와 Flocking 통합
- NavMesh로 기본 경로 찾기 (큰 장애물 회피)
- Flocking으로 유닛 간 충돌 회피 및 자연스러운 움직임
- 두 시스템의 장점을 합치기
- 장애물 회피 추가
- Obstacle Avoidance 규칙 구현
- 벽이나 지형지물을 감지해서 피하기
- Raycast로 전방 체크
- 성능 프로파일링
- 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 공식 문서 및 커뮤니티 예제들
'TIL' 카테고리의 다른 글
| [2025_12_05]프로토타입 발표 및 최종 팀 빌딩 (1) | 2025.12.05 |
|---|---|
| [2025_12_04]탑뷰 2d 게임 유닛 이동 AI개선 (0) | 2025.12.04 |
| [2025_12_02]뒷 유닛이 앞 유닛을 미는 문제(2d 물리) (0) | 2025.12.02 |
| [2025_12_01]기획 문서의 해석 (0) | 2025.12.01 |
| [2025_11_28]기획자와의 협업 프로젝트 (0) | 2025.11.28 |