1. Introduction
1.1. 현대 생태계 시뮬레이션의 필요성
전통적인 야외 관찰이나 실험 연구는 분명히 중요하지만, 시간과 공간의 제약이 크다. 특히 기후변화 같은 장기적이고 물리적으로 조작하기 힘든 것들을 실험으로 검증한다는 것은 현실적으로 불가능에 가깝다. 컴퓨터 시뮬레이션이 이런 문제를 해결할 수 있는 대안으로 주목받고 있지만, 기존 접근법들도 여전히 많은 한계를 보이고 있다.
1.2. 기존 생태계 시뮬레이션의 기술적 한계점들
1.2.1. 성능과 확장성 문제
지금까지 생태계 시뮬레이션 연구들을 보면 대부분 특정 알고리즘이나 특정 측면에만 집중하는 경우가 많았다. NetLogo, Repast 같은 널리 사용되는 에이전트 기반 모델링 플랫폼들은 기본적인 구현으로는 규모가 큰 시뮬레이션을 감당하기 어렵다 [2]. 천 개체만 넘어가도 성능이 급격히 떨어지는 경우가 대부분이고, 결국 실제 생태계 복잡성의 극히 일부만 다룰 수밖에 없다.
1.2.2. 환경 모델링의 한계
기존 시뮬레이션에서 환경은 대부분 정적이거나 실험의 환경이 다양하지 않은 경우가 많다. NetLogo 같은 플랫폼을 보면 기본적으로는 추상적인 격자 공간을 사용하고, 실제 지리 정보를 반영하려면 별도 확장 기능을 써야 한다 [1]. 이런 방식은 실제 생태계의 중요한 특성들을 놓치게 된다. 실제로는 지형이나 수계, 토양 조건, 미기후 같은 것들이 동식물의 행동과 생존에 직접적인 영향을 미친다. 이러한 확장된 생태계의 환경을 구축하는데 많은 시간이 드는 것도 있으며, 간단한 엔진으로는 제대로 모델링하기도 어렵다.
1.3. 게임 개발 기술의 생태학 응용 가능성
1.3.1. 대규모 실시간 시뮬레이션 기술
게임 산업에서는 지난 몇십 년간 실시간 대규모 시뮬레이션 기술 개발에 엄청난 투자를 해왔다. 전략 시뮬레이션 게임에서는 수만 유닛을 동시에 제어하고, MMORPG에서는 수천 명의 플레이어가 실시간으로 상호작용하며, RTS 게임에서는 복잡한 AI 시스템이 구현되는 것이 이미 일반적이다.
Unity 게임 엔진 같은 경우를 보면 Job System과 Burst 컴파일러를 통해서 멀티코어 CPU를 효율적으로 활용하는 병렬 처리가 가능하다 [3].
1.3.2. 절차적 콘텐츠 생성 기술의 활용
게임 개발 분야에서 발전된 절차적 콘텐츠 생성(PCG) 기술들은 생태계 시뮬레이션의 환경 모델링 문제를 해결하는 데 도움이 될 수 있다. Wave Function Collapse(WFC) 알고리즘은 간단한 국소 규칙에서 시작해서 전체적으로 일관성 있는 복잡한 패턴을 만들어낼 수 있고, Binary Space Partitioning(BSP)는 계층적으로 공간을 나누는 체계적인 방법을 제공한다.
이런 기술들을 쓰면 실제 생태계의 공간적 다양성이나 서식지 연결성, 자원 분포 같은 것들을 현실적으로 모델링하면서도, 시뮬레이션할 때마다 새로운 환경을 만들어서 다양한 상황을 테스트해볼 수 있을 것이다 [4] [5].
1.3.3. 게임 AI 행동 시스템
게임 AI에서 발전된 Finite State Machine(FSM)이나 Behaviour Tree 같은 기술들은 복잡한 에이전트 행동을 효율적으로 모델링할 수 있는 검증된 방법들이다. 이런 시스템들은 단순한 반사 행동부터 복잡한 의사결정까지 여러 행동 패턴들을 표현할 수 있다 [7].
2. Unity에서 다중 에이전트 처리를 위한 중앙화 비동기 처리
수백 에이전트가 동시에 활동하는 환경에서 각 에이전트의 독립적인 경로 계산은 시스템 전체의 성능 저하를 야기한다. 전통적으로 A* 알고리즘은 개별 에이전트마다 순차적으로 실행되어 왔으나, 이러한 접근법은 에이전트 수가 증가할수록 계산 복잡도가 선형적으로 증가하는 근본적 한계를 지닌다.
본 리포트에서는 Unity Job System과 Burst 컴파일러를 기반으로 한 병렬 A* 경로탐색 시스템을 제안한다. 제안된 시스템은 배치 처리와 공유 자료구조를 통해 메모리 효율성을 확보하고, 멀티코어 환경에서의 병렬 처리를 통해 성능 향상을 목표로 한다 [3].
2.1. 관련 연구 및 문제 정의
2.1.1. 기존 A* 구현의 성능 제약
A* 알고리즘은 휴리스틱 함수를 활용한 최적 경로 탐색 알고리즘으로 널리 사용되고 있다. 그러나 다중 에이전트 환경에서 각 에이전트가 독립적으로 A*를 실행할 경우 문제가 발생한다. 문제는 메모리 사용량의 중복성이다. 각 에이전트는 동일한 지형 정보에 대해 개별적인 Open Set과 Closed Set을 유지해야 하므로, N개 에이전트에 대해 N배의 메모리 오버헤드가 발생한다. 둘째, CPU 자원 활용이 비효율적이다. 순차 처리 방식은 멀티코어 프로세서의 병렬 처리 능력을 활용하지 못하여 하드웨어 성능의 일부분만을 사용한다.
2.1.2. 병렬 경로탐색 연구 동향
병렬 A* 알고리즘에 대한 연구는 주로 단일 에이전트의 탐색 과정을 병렬화하는 방향으로 진행되어 왔다. 그러나 다중 에이전트 환경에서는 각 에이전트의 탐색 작업을 독립적인 병렬 작업으로 처리하는 것이 더 효율적이다. 본 리포트는 후자의 접근법을 채택하여 에이전트별 경로탐색을 병렬화한다.
2.1.3 Unity NavMesh의 한계점
2.1.3.1. 정적 환경 종속성
NavMesh는 본질적으로 베이킹 기반 시스템이다. 환경이 변경될 때마다 전체 메쉬를 재구축해야 하는데, 이는 동적 장애물이 빈번한 환경에서 치명적이다.
NavMeshBuilder.BuildNavMesh();
2.1.3.2. 메모리 비효율성과 중복성
NavMesh는 각 에이전트가 독립적인 경로 계산 컨텍스트를 유지해야 한다. NavMesh는 개별 NavMeshAgent 컴포넌트와 각자의 경로 버퍼 만큼을 업데이트 한다.
2.1.3.3. 병렬 처리 한계
Unity NavMesh는 주 스레드에서 순차 처리된다. 에이전트 수가 증가하면 선형적으로 성능이 저하된다.
foreach(NavMeshAgent agent in agents)
agent.SetDestination(target);
2.1.3.4. 세밀한 제어 부족
NavMesh는 블랙박스 시스템이다. 경로 계산 과정을 커스터마이징하거나 특수한 비용 함수를 적용하기 어렵다. 제안 시스템은 A* 알고리즘을 직접 구현해 완전한 제어권을 제공한다.
2.1.3.5. 대각선 이동과 정밀도 문제
NavMesh의 삼각형 기반 표현은 격자 기반 정밀한 이동을 구현하기 어렵다.
2.1.3.6. Burst 컴파일러 호환성 부족
NavMesh API는 관리 코드 기반이어서 Burst 컴파일러의 최적화를 받을 수 없다.
2.1.3.7. 배치 처리 불가능
NavMesh는 개별 에이전트마다 즉시 처리해야 하므로 배치 최적화가 불가능하다.
2.1.3.8. 예측 가능성 부족
NavMesh의 성능은 지형의 복잡도와 에이전트 분포에 따라 예측하기 어렵게 변동된다.
결론적으로, NavMesh는 소규모 정적 환경에서는 편리하지만, 대규모 다중 에이전트 동적 환경에서는 메모리 비효율성, 병렬 처리 한계, 실시간 업데이트 불가능 등의 구조적 한계로 인해 부적합하다. 제안된 중앙화 병렬 A* 시스템이 이러한 문제들을 근본적으로 해결하는 대안이 된다.
2.2. 시스템 아키텍처 설계
2.2.1. 중앙화된 경로탐색 관리자
제안된 시스템의 핵심은 AStarManager 클래스로 구현된 중앙화된 경로탐색 관리 시스템이다. 이 시스템은 Singleton 패턴을 통해 전역적으로 접근 가능한 단일 인스턴스를 제공하며, 모든 에이전트의 경로 요청을 통합적으로 관리한다.
시스템의 주요 구성 요소는 다음과 같다:
- 공유 격자 구조(Shared Grid): 모든 에이전트가 공통으로 사용하는 지형 정보
- 요청 대기열(Request Queue): 에이전트들의 경로탐색 요청을 순차적으로 저장
- 배치 처리 배열: 고정 크기의 배치 단위로 요청을 처리하기 위한 자료구조
private NativeArray<PathNode> grid;
private Queue<PathRequest> requestQueue;
private NativeArray<PathRequest> batchRequests;
private NativeArray<PathResult> batchResults;
2.2.2. 배치 기반 처리 메커니즘
시스템은 개별 요청을 즉시 처리하는 대신, 일정한 크기의 배치로 묶어서 처리한다. 기본 배치 크기는 128개로 설정되어 있으며, 이는 메모리 사용량과 처리 지연시간 사이의 균형점을 고려하여 결정된 값이다. 배치 처리 방식은 Job System의 오버헤드를 최소화하고 일관된 성능을 보장한다.
private void ProcessBatch()
{
currentJobHandle.Complete();
ProcessResults();
int count = math.min(batchSize, requestQueue.Count);
if (count == 0) return;
AStar job = new AStar {
requests = batchRequests,
grid = grid,
gridWidth = gridWidth,
gridHeight = gridHeight,
maxPathLength = maxPathLength,
results = batchResults,
pathBuffer = pathBuffer
};
currentJobHandle = job.Schedule(count, math.max(1, count / 4));
}
2.2.3. 요청 중복 제거 및 생명주기 관리
시스템은 동일 에이전트로부터의 빈번한 요청을 방지하기 위해 시간 기반 필터링을 구현한다. 각 에이전트는 설정된 최소 간격(pathUpdateInterval) 내에서 하나의 요청만 처리되며, 이미 처리 중인 요청이 있는 경우 새로운 요청은 무시된다.
if (lastRequestTime.TryGetValue(agentId, out float lastTime))
{
if (Time.time - lastTime < pathUpdateInterval * 0.5f)
return;
}
또한 오래된 요청에 대한 정리 메커니즘을 통해 메모리 누수를 방지하고 시스템의 장기적 안정성을 보장한다.
2.3. Burst 최적화된 병렬 A* 구현
2.3.1 Job System 인터페이스 구현
A* 알고리즘은 IJobParallelFor 인터페이스를 구현한 구조체로 작성되었다. 이는 Unity의 Job System이 자동으로 작업을 여러 스레드에 분산 실행할 수 있게 한다. Burst 컴파일러의 최적화를 최대한 활용하기 위해 부동소수점 연산 모드를 Fast로, 정밀도를 Low로 설정했다.
[BurstCompile(CompileSynchronously = true, FloatMode = FloatMode.Fast,
FloatPrecision = FloatPrecision.Low)]
public struct AStar : IJobParallelFor
{
public void Execute(int index)
{
PathRequest request = requests[index];
PathResult result = new PathResult
{
requestId = request.requestId,
agentId = request.agentId,
success = false,
pathStartIndex = index * maxPathLength,
pathLength = 0
};
if (request.start.x == request.goal.x && request.start.y == request.goal.y)
{
result.success = true;
result.pathLength = 1;
pathBuffer[result.pathStartIndex] = request.goal;
results[index] = result;
return;
}
float distance = math.distance(request.start, request.goal);
SimpleAStar(index, request, ref result);
results[index] = result;
}
}
2.3.2 메모리 효율적인 자료구조 활용
각 Job 실행 시 필요한 임시 자료구조는 Allocator.Temp를 사용하여 할당하고, Job 완료 시 자동으로 해제되도록 구현했다. 이는 메모리 누수를 방지하고 가비지 컬렉션의 압박을 줄이는 효과를 가져온다.
private void SimpleAStar(int jobIndex, PathRequest request, ref PathResult result)
{
const int MAX_ITERATIONS = 1000;
const int MAX_OPEN_SET_SIZE = 512;
NativeMinHeap openSet = new NativeMinHeap(MAX_OPEN_SET_SIZE, Allocator.Temp);
NativeHashSet<int> closedSet = new NativeHashSet<int>(MAX_OPEN_SET_SIZE, Allocator.Temp);
NativeHashMap<int, int> cameFrom = new NativeHashMap<int, int>(MAX_OPEN_SET_SIZE, Allocator.Temp);
NativeHashMap<int, int> gScore = new NativeHashMap<int, int>(MAX_OPEN_SET_SIZE, Allocator.Temp);
openSet.Dispose();
closedSet.Dispose();
cameFrom.Dispose();
gScore.Dispose();
}
2.3.3 대각선 이동 처리 및 코너 컷팅 방지
8방향 이동을 지원하되, 대각선 이동 시 코너 컷팅을 방지하기 위한 검증 로직을 구현했다. 대각선 방향으로 이동할 때 인접한 두 직교 방향이 모두 통행 가능한 경우에만 이동을 허용한다.
if (dir % 2 == 1)
{
int2 checkPos1 = GetNeighborPosition(currentPos, (dir - 1) % 8);
int2 checkPos2 = GetNeighborPosition(currentPos, (dir + 1) % 8);
if (!IsValidPosition(checkPos1) || !IsValidPosition(checkPos2))
continue;
int checkIndex1 = GetIndex(checkPos1);
int checkIndex2 = GetIndex(checkPos2);
if (!grid[checkIndex1].isWalkable || !grid[checkIndex2].isWalkable)
continue;
}
2.4. 경로 후처리 및 최적화
2.4.1 경로 평활화 알고리즘
A* 알고리즘이 생성하는 격자 기반 경로는 계단 형태의 부자연스러운 모양을 가질 수 있다. 이를 개선하기 위해 시선 기반 경로 평활화 알고리즘을 구현했다. 이 알고리즘은 현재 위치에서 가장 멀리 보이는 지점까지 직선으로 연결하여 웨이포인트 수를 줄이고 보다 자연스러운 경로를 생성한다.
private List<int2> SmoothPath(List<int2> path)
{
if (path.Count <= 2)
return path;
List<int2> smoothed = new List<int2>();
smoothed.Add(path[0]);
int currentIndex = 0;
while (currentIndex < path.Count - 1)
{
int farthestVisible = currentIndex + 1;
for (int i = currentIndex + 2; i < path.Count; i++)
{
if (HasLineOfSight(path[currentIndex], path[i]))
farthestVisible = i;
else
break;
}
smoothed.Add(path[farthestVisible]);
currentIndex = farthestVisible;
}
return smoothed;
}
2.4.2 브레젠험 알고리즘을 이용한 시선 검사
두 지점 사이의 시선 검사는 브레젠험(Bresenham) 직선 알고리즘을 활용하여 구현했다. 이 방법은 부동소수점 연산을 피하고 정수 연산만으로 두 점 사이의 모든 격자를 순회하면서 장애물 존재 여부를 확인할 수 있어 계산 효율성이 높다.
private bool HasLineOfSight(int2 start, int2 end)
{
int x0 = start.x; int y0 = start.y;
int x1 = end.x; int y1 = end.y;
int dx = math.abs(x1 - x0);
int dy = math.abs(y1 - y0);
int x = x0; int y = y0;
int n = 1 + dx + dy;
int x_inc = (x1 > x0) ? 1 : -1;
int y_inc = (y1 > y0) ? 1 : -1;
int error = dx - dy;
dx *= 2; dy *= 2;
for (; n > 0; --n)
{
if (!IsValidPosition(new int2(x, y)) || !IsWalkable(new int2(x, y)))
return false;
if (error > 0)
{
x += x_inc;
error -= dy;
}
else
{
y += y_inc;
error += dx;
}
}
return true;
}
2.5. 동적 환경 지원 및 유지보수성
2.5.1 실시간 장애물 업데이트
시뮬레이션 환경에서 장애물의 생성, 제거, 이동이 빈번하게 발생할 수 있다. 이에 대응하기 위해 격자의 특정 영역만을 선택적으로 업데이트하는 메커니즘을 구현했다. 전체 격자를 재생성하는 대신 영향받는 영역만을 업데이트하여 성능 저하를 최소화한다.
public void UpdateObstacle(Vector3 worldPos, float radius, bool isWalkable)
{
int2 gridPos = WorldToGrid(worldPos);
int gridRadius = Mathf.CeilToInt(radius / cellSize);
for (int x = -gridRadius; x <= gridRadius; x++)
{
for (int y = -gridRadius; y <= gridRadius; y++)
{
int2 checkPos = gridPos + new int2(x, y);
if (!IsValidPosition(checkPos))
continue;
float distance = math.distance(gridPos, checkPos);
if (distance <= gridRadius)
{
int index = checkPos.x + checkPos.y * gridWidth;
PathNode node = grid[index];
node.isWalkable = isWalkable;
grid[index] = node;
}
}
}
}
2.5.2 메모리 관리 및 시스템 안정성
시스템의 장기적 안정성을 위해 여러 단계의 메모리 관리 메커니즘을 구현했다. 오래된 경로 요청은 주기적으로 정리되며, NativeArray와 같은 비관리 메모리 자원은 시스템 종료 시 명시적으로 해제된다.
protected override void OnDestroy()
{
currentJobHandle.Complete();
if (grid.IsCreated) grid.Dispose();
if (batchRequests.IsCreated) batchRequests.Dispose();
if (batchResults.IsCreated) batchResults.Dispose();
if (pathBuffer.IsCreated) pathBuffer.Dispose();
base.OnDestroy();
}
2.6. 시스템 특성 분석
2.6.1 메모리 효율성
제안된 시스템의 가장 큰 장점 중 하나는 메모리 사용량의 효율성이다. 모든 에이전트가 단일 공유 격자를 참조함으로써 중복 메모리 할당을 방지한다.
2.6.2 확장성
배치 처리 방식은 에이전트 수의 증가에 대해 선형적인 확장성을 제공한다. 배치 크기는 고정되어 있지만, 배치 수는 요청량에 따라 동적으로 증가할 수 있다. 또한 Job System의 특성상 사용 가능한 CPU 코어 수에 비례하여 처리 성능이 향상된다.
2.6.3 응답성
배치 처리로 인한 지연시간은 최대 한 프레임 정도이며, 이는 대부분의 실시간 시뮬레이션에서 허용 가능한 수준이다. 중요한 것은 시스템이 일정한 처리 간격을 유지하여 예측 가능한 성능을 제공한다는 점이다.
2.7 기존 시스템과의 비교분석
비교 환경은 MultiAgent(100 에이전트)에서 장애물과 목표물을 같은 위치에 배치하고 비교한다.
[그림 1]에서 하얀색으로 길게 늘어진 막대는 장애물이며, 오른쪽 노란 선분들이 가르키고 있는 객체가 목표이다. 객체들이 현재 뭉쳐있는 상태라 많아보이지 않을 수 있다.
[그림 1]과 같은 환경에서 기본적인 ASTAR를 실행하는 것과 제안된 ASTAR를 실행하는 것의 성능을 분석하면 아래와 같다:
[그림 2]와 [그림 3]는 Unity의 Profiler 기능을 이용해서 측정했다.
메트릭 | 순차 A* | 병렬 A* |
---|---|---|
메인 스레드 시간 | 74.11ms | 3.94ms |
평균 FPS | 43 | 120 |
[표 1]을 토대로 비교해보자면 메인 스레드 시간과 FPS의 상태를 본다면 얼마나 제안된 방법이 효과적인지 알 수 있다.
3. Unity에서 행동 모델링(FSM vs Behaviour Tree)
3.1. FSM (Finite State Machine)
3.1.1. 기본적인 FSM의 형태
유한 상태 기계는 시스템이 가질 수 있는 유한한 개수의 상태와 이들 간의 전이 규칙으로 구성되는 수학적 모델이다. 전통적인 FSM은 상태(State), 전이(Transition), 이벤트(Event) 또는 조건(Condition)이라는 세 가지 핵심 요소로 구성된다.
기본적인 FSM에서 각 상태는 독립적인 행동이나 조건을 나타내며, 특정 조건이 만족될 때 다른 상태로 전이한다. 전이는 즉시 발생하며, 시스템은 항상 정확히 하나의 상태에만 존재할 수 있다. 이러한 단순함이 FSM의 가장 큰 장점이자 특징이다 [7].
3.1.2. 본 구현에서의 확장점
3.1.2.1. 제네릭 기반 타입 안전성
본 구현에서는 C#의 제네릭 시스템을 활용하여 타입 안전성과 재사용성을 크게 향상시켰다.
public interface IState<T>
{
void Enter(T owner);
void Execute(T owner);
void Exit(T owner);
}
public class StateMachine<T>
{
private T owner;
private IState<T> currentState;
private IState<T> previousState;
private Dictionary<Type, IState<T>> states;
}
제네릭 <T>
매개변수를 통해 어떤 타입의 객체에도 적용할 수 있는 범용적인 상태 기계를 구현했다.
3.1.2.2. 명시적 생명주기 관리
전통적인 FSM과 달리 본 구현은 상태의 생명주기를 명시적으로 관리한다.
public void ChangeState<TState>() where TState : IState<T>
{
Type stateType = typeof(TState);
if (states.ContainsKey(stateType))
{
if (currentState != null)
{
currentState.Exit(owner);
previousState = currentState;
}
currentState = states[stateType];
currentState.Enter(owner);
}
}
Enter
, Execute
, Exit
메서드를 통해 상태의 시작, 실행, 종료 단계를 명확히 구분한다. 이는 각 단계에서 필요한 초기화와 정리 작업을 체계적으로 수행할 수 있게 한다.
3.1.2.3. 딕셔너리 기반 상태 관리
상태들을 Dictionary<Type, IState<T>>
로 관리하는 방식은 성능과 유연성 측면에서 중요한 개선이다.
public void AddState(IState<T> state)
{
states[state.GetType()] = state;
}
public void ChangeState<TState>() where TState : IState<T> {
Type stateType = typeof(TState);
if (states.ContainsKey(stateType))
{
// code ...
}
}
타입을 키로 사용하는 딕셔너리 구조를 통해 O(1) 시간 복잡도로 상태에 접근할 수 있다. 또한 컴파일 타임에 상태 타입을 검증할 수 있어 잘못된 상태 참조로 인한 오류를 방지한다.
3.1.2.3. 이전 상태 추적 기능
많은 기본 FSM 구현에서 제공하지 않는 이전 상태 추적 기능을 구현했다.
public void RevertToPreviousState()
{
if (previousState != null)
{
if (currentState != null)
{
currentState.Exit(owner);
}
currentState = previousState;
currentState.Enter(owner);
}
}
이 기능을 통해 일시적인 상태 변경 후 원래 상태로 돌아가는 패턴을 쉽게 구현할 수 있다.
3.1.3. 생태계 시뮬레이션 구현 시의 이점
3.1.3.1. 직관적인 동물 행동 모델링
FSM의 명확한 상태 구분은 동물의 행동을 직관적으로 모델링할 수 있게 한다. 각 상태가 명확한 책임을 가지고 있어 코드를 이해하기 쉽고 수정하기 쉽다. 동물의 행동이 예상과 다를 때 해당 상태만 확인하면 원인을 쉽게 파악할 수 있다.
3.1.3.2. 높은 성능과 메모리 효율성
FSM은 현재 상태 정보만 유지하면 되므로 매우 적은 메모리를 사용한다. 대규모 생태계 시뮬레이션에서 수천 마리의 동물을 동시에 시뮬레이션할 때 이러한 효율성은 매우 중요하다. 각 에이전트마다 최소한의 메모리만 사용하고 필요한 로직만 실행하므로 시스템 리소스를 효과적으로 활용할 수 있다.
3.1.3.3. 예측 가능한 행동과 균형 조정
FSM의 결정론적 특성을 통해 동물 행동의 균형을 쉽게 조정할 수 있다. 각 전이 조건이 명확하게 정의되어 있어 게임 밸런스를 조정할 때 어떤 값을 변경해야 하는지 쉽게 파악할 수 있다.
3.1.3.4. 단순한 행동의 효율적 구현
복잡하지 않은 동물 행동의 경우 FSM이 가장 효율적인 선택이다. 기본적인 생존 행동만 필요한 에이전트들을 구현할 때는 FSM의 단순성이 큰 장점이 된다.
3.2. Behaviour Tree
3.2.1. 기본적인 Behaviour Tree의 형태
Behaviour Tree는 게임 AI와 로보틱스 분야에서 복잡한 행동을 계층적으로 구조화하기 위해 개발된 모델이다. 트리 구조를 통해 복잡한 행동을 작은 단위의 행동들로 분해하고, 이들을 조합하여 더 복잡한 행동 패턴을 만들어낸다 [7].
기본적인 노드 타입들은 다음과 같이 구성된다:
기본 노드 타입:
- Composite Nodes: 자식 노드들을 실행하는 방식을 결정
- Selector (OR): 자식 중 하나가 성공할 때까지 순서대로 실행
- Sequence (AND): 모든 자식이 성공해야 성공
- Parallel: 여러 자식을 동시에 실행
- Decorator Nodes: 자식 노드의 행동을 수정
- Inverter: 결과를 반대로 변경
- Repeater: 특정 조건까지 반복 실행
- Cooldown: 일정 시간 간격으로 실행 제한
- Leaf Nodes: 실제 행동이나 조건을 수행
- Action: 구체적인 행동 실행
- Condition: 조건 검사
public enum NodeState
{
Running,
Success,
Failure
}
기본 형태의 Behaviour Tree는 매 프레임마다 루트에서 시작하여 트리를 탐색하며, 각 노드는 NodeState
열거형으로 정의된 세 가지 상태 중 하나를 반환한다. 이러한 단순한 구조만으로도 복잡한 AI 행동을 표현할 수 있지만, 실제 게임이나 시뮬레이션에 적용하기에는 몇 가지 한계가 있다.
3.2.2. 본 구현에서의 확장점
3.2.2.1. 노드 생명주기 관리 시스템
본 구현에서는 기본적인 행동 트리 구조에서 한 걸음 나아가 노드의 생명주기를 명시적으로 관리하는 시스템을 도입했다.
public virtual NodeState Evaluate()
{
bool isCurrentlyRunning = (state == NodeState.Running);
state = DoEvaluate();
if (wasRunning && state != NodeState.Running)
{
OnExitNode();
}
else if (!wasRunning && state == NodeState.Running)
{
OnEnterNode();
}
wasRunning = (state == NodeState.Running);
return state;
}
protected virtual void OnEnterNode() { }
protected virtual void OnExitNode() { }
wasRunning
플래그를 통해 이전 프레임의 실행 상태를 추적하고, 상태 변화에 따라 OnEnterNode
와 OnExitNode
메서드를 자동으로 호출한다. 이는 전통적인 행동 트리에서는 제공하지 않는 중요한 기능이다. 많은 AI 행동들은 시작 시점에서 초기화 작업이 필요하고, 종료 시점에서 정리 작업이 필요하다. 예를 들어, 이동 행동을 시작할 때는 경로를 계산하고, 종료할 때는 애니메이션을 정리해야 한다.
3.2.2.2. 동적 중단 메커니즘
기본적인 행동 트리는 우선순위 변경에 따른 행동 중단을 처리하는 표준적인 방법을 제공하지 않는다. 본 구현에서는 재귀적 중단 시스템을 구축했다.
public virtual void Interrupt()
{
foreach (Node child in children)
child.Interrupt();
if (wasRunning)
{
OnInterrupted?.Invoke();
OnExitNode();
state = NodeState.Failure;
wasRunning = false;
}
}
이 메커니즘은 높은 우선순위의 행동이 활성화될 때 현재 실행 중인 모든 하위 행동을 일관되게 중단할 수 있게 한다. OnInterrupted
액션 델리게이트를 통해 외부 시스템에서 중단 이벤트를 감지할 수 있도록 하여, 행동 트리와 다른 게임 시스템 간의 통합을 용이하게 했다.
3.2.2.3. 게임 엔진 통합 최적화
Unity와의 긴밀한 통합을 위해 ActionNode
클래스에서 핵심 컴포넌트들에 직접 접근할 수 있도록 구현했다.
public abstract class ActionNode : Node
{
protected Transform transform;
protected Animator animator;
protected Rigidbody2D rigidbody;
protected bool isActive = false;
public ActionNode(Transform transform, bool forceComplete = false, string cooldownKey = null)
{
this.transform = transform;
this.mustComplete = forceComplete;
this.cooldownKey = cooldownKey;
animator = transform.GetComponent<Animator>();
rigidbody = transform.GetComponent<Rigidbody2D>();
}
}
이러한 설계는 AI 프로그래머가 복잡한 인터페이스나 중간 계층 없이 직접적으로 게임 오브젝트를 조작할 수 있게 한다. 생태계 시뮬레이션에서 동물의 이동, 애니메이션, 물리 상호작용을 즉시 제어할 수 있어 개발 효율성이 크게 향상된다.
3.2.2.4. 강제 완료 메커니즘
특정 행동이 중단되지 않고 완료되어야 하는 상황을 처리하기 위한 기능이다.
public sealed override NodeState Evaluate()
{
if (mustComplete && isActive && state == NodeState.Running)
{
NodeState result = DoEvaluate();
if (wasRunning && result != NodeState.Running) {
OnExitNode();
isActive = false;
}
if (result == NodeState.Success && !string.IsNullOrEmpty(cooldownKey)) {
Cooldown.StartCooldown(cooldownKey);
}
state = result;
wasRunning = (state == NodeState.Running);
return result;
}
NodeState evaluationResult = base.Evaluate();
if (evaluationResult == NodeState.Success && !string.IsNullOrEmpty(cooldownKey)) {
Cooldown.StartCooldown(cooldownKey);
}
return evaluationResult;
}
mustComplete
플래그를 통해 공격이나 중요한 애니메이션과 같이 중간에 중단되면 안 되는 행동들을 보호할 수 있다. 이는 자연스러운 동물 행동 구현에 필수적인 기능이다.
3.2.2.5. 쿨다운 시스템
행동의 빈도를 제어하여 더욱 현실적인 AI 행동을 구현한다.
protected string cooldownKey = null;
if (result == NodeState.Success && !string.IsNullOrEmpty(cooldownKey)) {
Cooldown.StartCooldown(cooldownKey);
}
문자열 키 기반의 쿨다운 시스템을 통해 서로 다른 행동들이 독립적인 쿨다운을 가지거나, 관련된 행동들이 같은 쿨다운을 공유할 수 있다.
3.2.2.6. 물리 시뮬레이션 분리
Unity의 고정 업데이트 사이클과 일반 업데이트 사이클을 분리하여 처리한다.
public virtual void FixedEvaluate()
{
foreach(Node child in children)
child.FixedEvaluate();
}
물리와 관련된 AI 로직을 별도로 처리할 수 있는 확장점을 제공한다. 생태계 시뮬레이션에서 동물의 이동이나 충돌 처리와 같은 물리 기반 행동을 정확하게 구현할 수 있다.
4. WFC와 BSP 통합 알고리즘 분석
본 리포트는 절차적 환경 생성(PCG) 분야의 두 핵심 알고리즘, Wave Function Collapse(WFC)와 Binary Space Partitioning(BSP)의 통합 모델을 실제 Unity C# 스크립트 구현을 통해 심층적으로 분석한다. 이론적 개념이 코드 로직으로 전환되는 과정과 두 알고리즘이 유기적으로 결합하여 시너지를 창출하는 방식에 초점을 맞춘다. 궁극적으로 본 통합 모델이 생태계 시뮬레이션을 위한 유연하고 통제 가능한 실험 환경을 구축하는 데 효과적인 도구임을 제시하고자 한다.
4.1. Wave Function Collapse (WFC)
4.1.1. WFC의 핵심 원리: 엔트로피와 제약 전파
Wave Function Collapse는 국소적 규칙으로부터 전역적으로 일관성 있는 패턴을 생성하는 비반복적 타일링 알고리즘이다 [5]. 그 핵심 원리는 양자역학의 개념에서 차용되었으며, 생성 대상인 그리드의 각 셀은 초기에 모든 가능한 타일 상태를 포함하는 ‘중첩(superposition)’ 상태로 시작한다. 이때 각 셀이 가질 수 있는 상태의 가짓수를 ‘엔트로피(entropy)‘라고 정의한다.
알고리즘은 관측-전파(Observe-Propagate) 루프를 반복한다. 먼저 관측 단계에서는 전체 그리드에서 가장 낮은 엔트로피를 가진 셀, 즉 가장 적은 가능성을 가진 셀을 선택한다. 이어서 붕괴 단계에서는 선택된 셀의 상태를 여러 가능성 중 하나로 확정시키며, 이 선택은 각 타일의 가중치에 따른 확률적 선택이 될 수 있다.
마지막으로 전파 단계에서는 하나의 셀이 붕괴되면 그 결정이 새로운 제약 조건이 되어 인접 셀들에게 영향을 미치며, 붕괴된 셀의 인접 규칙에 위배되는 타일들을 주변 셀들의 가능성 목록에서 제거한다.
이 과정을 통해 주변 셀들의 엔트로피가 감소하며, 연쇄적인 제약 전파가 더 이상 변화가 없을 때까지 계속된다. 모든 셀의 엔트로피가 1이 될 때까지 이 루프를 반복하면, 국소적 인접 규칙만을 사용했음에도 불구하고 전체적으로는 매우 복잡하고 자연스러운 거대 패턴이 완성된다.
4.1.2. 지역적 WFC 구현과 계산 복잡도 관리
제공된 스크립트에서 WFC는 BSP가 구획한 각 지역 내부의 세부 생태계를 묘사하는 데 사용되며, 이는 WFC의 계산 복잡도를 관리하는 핵심적인 최적화 전략이다. GenerateRegionalWFC
함수가 이 과정을 총괄하며, 가장 불확실성이 낮은 셀을 찾는 관측 단계는 FindLowestEntropyCellInRegion
함수를 통해 구현된다.
이 함수는 지역 내의 모든 셀을 순회하면서 붕괴되지 않은 셀들 중에서 가능성 목록의 길이가 가장 짧은 셀을 찾는다. 동일한 엔트로피를 가진 셀이 여러 개 있을 경우, 모든 후보를 수집한 후 무작위로 하나를 선택함으로써 생성 결과의 다양성을 확보한다. 이러한 접근 방식은 결정론적 선택으로 인한 패턴의 경직성을 방지하는 중요한 역할을 한다.
셀이 선택되어 CollapseCellInRegion
함수를 통해 붕괴되면, PropagateConstraintsInRegion
함수가 전파 단계를 수행한다. 이 함수는 너비 우선 탐색(BFS) 방식의 큐를 사용하여 붕괴된 셀로부터 시작해 영향을 받는 모든 인접 셀들로 제약 조건을 전파한다. 각 셀의 WFCRule을 기준으로 인접한 미붕괴 셀들의 가능성 리스트를 갱신하여, 새로운 제약 조건에 위배되는 타일 옵션들을 체계적으로 제거한다.
지역적 WFC 접근법의 가장 큰 장점은 거대한 맵 전체를 단일 WFC 시스템으로 처리할 때 발생하는 조합 폭발 문제를 원천적으로 방지한다는 점이다. 전체 맵이 100x100 크기라면 10,000개의 셀을 동시에 처리해야 하지만, 이를 10개의 지역으로 나누면 각각 평균 1,000개의 셀만 처리하면 되어 계산 복잡도가 현저히 감소한다. 동시에 각 지역의 고유한 생태학적 특성을 효과적으로 부여할 수 있는 기반이 된다.
4.2. Binary Space Partitioning (BSP)
4.2.1. BSP의 수학적 원리와 공간 조직화
Binary Space Partitioning(BSP)은 주어진 공간을 분할 평면을 사용해 재귀적으로 두 개의 부분 공간으로 나누는 알고리즘이다 [8]. 이 과정은 이진 트리 자료구조를 형성하는데, 각 노드는 공간의 한 영역을, 자식 노드들은 부모 노드가 분할된 두 개의 하위 영역을 나타낸다. 분할은 특정 종료 조건이 충족될 때까지 반복되며, 일반적으로 영역의 최소 크기나 트리의 최대 깊이를 기준으로 한다.
이 알고리즘의 본질적인 계층성과 분할-정복(Divide and Conquer) 접근 방식은 대규모 공간을 관리 가능한 단위로 체계적으로 조직화하는 데 매우 효율적이다. 전통적으로 게임의 던전이나 건물 내부의 방과 복도를 생성하는 데 사용되어 왔으나, 본 연구의 맥락에서는 서로 다른 기후와 특징을 가진 거대 생물군계를 구획하는 이상적인 도구로 활용된다.
BSP의 핵심적 장점은 생성된 구조가 자연스럽게 계층적 관리와 탐색이 가능하다는 점이다. 트리의 각 레벨은 서로 다른 규모의 공간 조직화를 나타내며, 루트 노드에서는 전체 대륙 수준의 거시적 구조를, 잎 노드에서는 개별 생태 지역 수준의 미시적 구조를 다룰 수 있다. 이러한 다중 스케일 접근법은 복잡한 생태계의 자연스러운 위계 구조를 모방하는 데 특히 유용하다.
4.2.2. 적응적 분할 전략과 생태학적 의미 부여
스크립트의 CreateBSPRegions
와 SplitBSPNode
함수는 BSP의 재귀적 분할 원리를 직접적으로 구현하되, 생태계 생성에 특화된 몇 가지 고도화된 기법을 포함한다. SplitBSPNode
함수는 단순한 무작위 분할 대신 영역의 종횡비를 고려한 적응적 분할 전략을 사용한다.
구체적으로, 현재 영역의 가로세로 비율이 1.5 이상이면 세로 분할을 강제하고, 세로가로 비율이 1.5 이상이면 가로 분할을 강제한다. 이는 극단적으로 길쭉한 영역이 생성되는 것을 방지하여 각 지역이 상대적으로 균형 잡힌 형태를 유지하도록 한다. 이러한 형태적 제약은 실제 지리학에서 관찰되는 생태 지역의 특성을 반영한 것으로, 너무 세로로 긴 지역은 기후의 급격한 변화를, 너무 가로로 긴 지역은 생태적 다양성의 부족을 초래할 수 있기 때문이다.
분할된 영역들이 단순한 기하학적 구획에서 생태학적 의미를 갖춘 지역으로 변화하는 과정은 AssignRegionalCharacteristics
함수에서 이루어진다. 이 함수는 각 구역의 맵 내 상대적 위치를 기반으로 RegionType을 결정하는데, 실험에 사용된 설정은 필자가 시연에 적절한 예시로 설정했다. 북쪽 영역은 한대 기후의 특성을, 남쪽 영역은 건조 기후의 특성을 부여받도록 했다. 이러한 지리적 결정론은 실제 지구의 위도별 기후 분포를 단순화하여 모델링한 것이다.
각 RegionType에 대해 BiomeRegionSettings에 미리 정의된 규칙에 따라 해당 구역에서 생성될 수 있는 바이옴 목록과 중심이 되는 주도 바이옴이 할당된다. 예를 들어, Northern 지역은 Snow, Mountain, Forest 바이옴이 허용되며 이 중 하나가 주도 바이옴으로 선정된다.
4.3. 통합적 방법론
4.3.1. bspInfluence를 통한 알고리즘 간 균형 조절
[그림 6]에서 확인할 수 있듯이, 두 알고리즘 간의 영향력을 동적으로 조절할 수 있는 bspInfluence
파라미터이다. 이 값은 0에서 1 사이의 실수로, 0에 가까울수록 순수한 WFC의 자유로운 패턴 생성을, 1에 가까울수록 BSP의 구조적 제약을 강하게 반영한다. 이러한 연속적 조절 방식은 이산적인 알고리즘 선택보다 훨씬 유연하고 세밀한 제어를 가능하게 한다.
bspInfluence
의 효과는 CollapseCellInRegion
함수 내에서 구체적인 가중치 로직으로 구현된다. WFC의 셀 붕괴 과정에서 각 타일 타입의 선택 확률을 계산할 때, BSP에 의해 할당된 지역적 바이옴에 추가적인 가중치를 부여하는 것이다. 이 지역에 허용된 바이옴일 경우 기본 가중치에 (1 + bspInfluence)
배수를 곱하고, 주도 바이옴일 경우에는 추가로 (1 + bspInfluence × 0.5)
배수를 더 곱한다.
이러한 수식적 접근은 bspInfluence
값이 증가함에 따라 지역적 바이옴의 선택 확률이 지수적으로 증가하도록 설계되었다. 예를 들어 bspInfluence
가 0.5일 때, 허용된 바이옴은 1.5배의 가중치를, 주도 바이옴은 1.75배의 가중치를 받는다. 만약 bspInfluence
가 0.9로 증가하면 각각 1.9배와 2.35배의 가중치를 받게 되어, BSP의 구조적 의도가 WFC의 확률적 생성 과정을 강력하게 영향을 미치게 된다.
4.3.2. 시드 배치 전략과 구조적 안정성 확보
높은 bspInfluence
값에서는 단순한 가중치 조정을 넘어서 PlaceSeedCells
함수를 통한 시드 배치 전략이 활용된다. 이 함수는 각 지역의 중심부에 해당 지역의 주도 바이옴으로 이미 붕괴된 시드 셀들을 미리 배치함으로써, WFC 생성 과정이 시작되기 전에 구조적 앵커 포인트를 제공한다.
시드의 배치 범위는 지역 크기의 20%에 bspInfluence
값을 곱한 반지름으로 결정되므로, BSP의 영향력이 클수록 더 넓은 영역에 시드가 배치된다. 이는 WFC의 엔트로피 기반 생성이 무작위성에만 의존하지 않고 BSP가 설계한 거시적 구조를 중심으로 전개되도록 유도하는 핵심 메커니즘이다. 시드 셀들로부터 시작된 제약 전파는 주변 지역으로 해당 바이옴의 특성을 확산시키며, 결과적으로 지역의 중심부는 강한 정체성을, 경계부는 상대적으로 혼재된 특성을 갖게 된다.
이러한 중심-경계 구조는 실제 생태학에서 관찰되는 핵심지역(core area)과 전이대(ecotone)의 개념을 자연스럽게 모방한다. 핵심지역에서는 해당 생태계의 전형적 특성이 강하게 나타나고, 인접한 생태계 간의 경계에서는 두 생태계의 특성이 혼재되어 나타나는 현상이 컴퓨터 알고리즘으로 자연스럽게 재현되는 것이다.
4.4. 후처리 시스템
4.4.1. 경계 블렌딩을 통한 자연스러운 전이 구현
알고리즘적 생성만으로는 종종 인위적이거나 급작스러운 전이가 나타날 수 있다. 특히 BSP의 명확한 경계선은 자연 생태계에서는 거의 관찰되지 않는 급격한 바이옴 변화를 만들어낼 수 있다. 이를 해결하기 위해 ApplyBoundaryBlending
함수는 구역 경계 근처에서 가중 평균을 사용한 속성 블렌딩을 수행한다.
블렌딩 과정은 각 타일의 구역 경계로부터의 거리를 기준으로 한다. blendingRadius
값 이하의 거리에 있는 모든 타일에 대해, 주변 타일들의 생태학적 속성을 거리 기반 가중치로 평균화한다. 가중치는 거리에 반비례하므로 가까운 타일의 영향이 더 크게 반영되며, 이는 자연스러운 확산 효과를 만들어낸다.
주목할 점은 타일의 타입 자체는 변경되지 않고 fertility, moisture, temperature와 같은 수치적 속성만 블렌딩된다는 것이다. 즉, 사막 타일이 숲 타일로 바뀌지는 않지만 인접한 숲 지역의 영향으로 습도가 약간 증가하고 온도가 약간 감소할 수 있다. 이러한 섬세한 접근 방식은 바이옴의 기본적 정체성은 유지하면서도 경계에서의 급격한 속성 변화를 완화하여 생태계 전이를 구현한다.
4.4.2. 고립 타일 정리와 연결성 개선
절차적 생성의 확률적 특성으로 인해 주변과 완전히 다른 특성을 가진 고립된 타일들이 종종 생성된다. 이러한 고립 타일들은 시각적으로 부자연스러울 뿐만 아니라 생태학적으로도 비현실적이다. CleanupIsolatedTiles
함수는 각 타일 주변 8방향을 검사하여 자신과 동일한 타입의 이웃이 1개 이하인 경우 고립된 것으로 판단하고, 해당 타일을 주변에서 가장 빈번하게 나타나는 타일 타입으로 교체한다.
이러한 후처리는 단순해 보이지만 생성 품질에 미치는 영향은 상당하다. 고립 타일의 제거는 각 바이옴 영역의 연속성과 응집성을 높여 더욱 자연스럽고 설득력 있는 지형을 만들어낸다. 동시에 시각적 노이즈를 줄여 전체적인 맵의 가독성을 향상시킨다.
물 타일에 대해서는 특별한 연결성 개선 로직이 적용된다. ImproveWaterConnectivity
함수는 기존의 물 타일들을 식별한 후, 일정 범위 내에 있는 다른 물 타일들을 선형 경로로 연결한다. 이는 강과 호수의 자연스러운 수계망을 모방한 것으로, 분리된 물 영역들을 유기적으로 연결하여 더욱 현실적인 수문학적 구조를 만들어낸다. 연결 과정에서는 기존의 풀이나 숲 지역만을 물로 변환하여 산이나 사막 같은 부적절한 지역을 통과하지 않도록 제한한다.
4.5. 개선 방안
WFC는 전체적인 구조를 잘 담아내는데 문제가 있다. 결과를 보면 알 수 있듯이 아직까지 ‘자연스럽다’ 라고 생각이 들지는 않는다. 또한 아직 자연이라고는 생각이 들지 않는다. 나무, 풀 등 식생이 존재하지 않으며, 생성 로직 또한 소개되지 않았다. 그래서 자연스러운 생태계 생성과 더불어 식생을 만드는데 필요한 알고리즘을 [4], [5]의 논문을 기반으로 구현을하여 개선할 수 있다.
절차적 생성으로 식생을 생태학적 원리에 기반하여 생성하며, 강화학습을 통해서 자연스러운 환경 타일 등을 생성하도록 만들어 현재의 구현 문제점을 보완한다.
5. 결론 및 향후 연구 방향
5.1. 연구 성과 및 기여점
5.1.1. 성능 최적화 달성
본 리포트에서 제안한 Unity Job System 기반 중앙화 병렬 A* 시스템은 기존 순차 처리 방식 대비 18.8배의 성능 향상을 달성했다. 메인 스레드 처리 시간을 74.11ms에서 3.94ms로 단축하고 평균 FPS를 43에서 120으로 개선한 것은 대규모 생태계 시뮬레이션의 실시간 처리 가능성을 크게 높인 성과다.
특히 배치 처리 방식과 공유 자료구조를 통한 메모리 효율성 확보는 수천 개체의 동시 시뮬레이션을 가능하게 하는 핵심 기반 기술이 되었다. 이는 기존 NetLogo, Repast 같은 플랫폼이 천 개체 수준에서 성능 저하를 보이는 한계를 극복한 것이다 [1].
5.1.2. 유연한 행동 모델링 프레임워크 구축
FSM과 Behaviour Tree의 심층적 비교 분석을 통해 에이전트 복잡도와 환경 특성에 따른 적응적 선택 기준을 제시했다. 단순 에이전트에는 FSM의 효율성을, 복잡한 에이전트에는 Behaviour Tree의 표현력을 활용하는 하이브리드 접근법은 계산 리소스와 행동 복잡성 사이의 최적 균형점을 제공한다.
특히 생명주기 관리, 동적 중단 메커니즘, 강제 완료 시스템 등의 확장 기능을 통해 자연스러운 동물 행동 패턴 구현이 가능해졌다. 이는 전통적인 게임 AI 기법을 생태계 시뮬레이션 분야로 성공적으로 확장 가능성을 제안한 것이다.
5.2. 시스템의 한계점 및 개선 과제
5.2.1. 환경 모델의 사실성 부족
현재 구현된 WFC+BSP 통합 시스템은 기본적인 바이옴 분포만을 다루며, 실제 생태계의 복잡한 상호작용을 충분히 반영하지 못한다. 식생의 부재, 수계망의 단순성, 토양-기후-생물군 간의 피드백 메커니즘 부족 등이 주요 한계점이다.
특히 현재의 타일 기반 접근법은 연속적인 환경 변화나 미기후 효과를 표현하기에 해상도가 제한적이다. 보다 사실적인 생태계 시뮬레이션을 위해서는 다중 스케일 환경 모델링이 필요하다.
5.2.2. 확장성과 모듈화의 개선 필요
각 구성 요소(경로탐색, 행동 모델링, 환경 생성)가 상대적으로 독립적으로 구현되어 있어, 시스템 간 유기적 상호작용을 구현하기에는 통합 아키텍처가 부족하다. 특히 환경 변화가 에이전트 행동에 미치는 영향이나, 에이전트 활동이 환경에 미치는 피드백 효과를 체계적으로 다루는 프레임워크가 필요하다.
5.3. 향후 연구 방향
5.3.1. 강화학습 기반 적응형 생태계
에이전트의 행동 패턴이 환경과의 상호작용을 통해 동적으로 진화하는 시스템을 구축할 수 있다. 개별 에이전트는 강화학습을 통해 최적 생존 전략을 학습하고, 집단 차원에서는 유전 알고리즘을 통해 행동 특성이 세대를 거쳐 전승되는 모델을 구현할 수 있다.
이는 기존의 고정된 행동 규칙에서 벗어나 실제 진화 과정을 모방한 동적 생태계 시뮬레이션을 가능하게 할 것이다.
5.3.2. 다중 스케일 환경-에이전트 상호작용 모델
현재의 타일 기반 환경을 확장하여 미시적(개체 수준), 중시적(집단 수준), 거시적(생태계 수준)으로 구분된 다중 스케일 모델링을 도입할 수 있다. 각 스케일에서 발생하는 현상들이 상위/하위 스케일에 미치는 영향을 체계적으로 모델링하여 더욱 사실적인 생태계 역학을 구현할 수 있다.
5.4. 결어
본 리포트는 게임 개발 기술을 생태계 시뮬레이션 분야에 적용하여 성능, 개발 효율성 측면에서 의미 있는 진전을 이루었다. 더 나아가 이러한 기술의 적용은 컴퓨터 시뮬레이션이 환경 문제 해결, 예측과 같은 과제를 기여할 수 있는 가능성을 제시했다.
물론 현재의 구현은 실제 생태계의 복잡성을 모두 담아내기에는 여전히 한계가 있다. 하지만 제시된 방법론과 기술적 기반은 향후 더욱 정교하고 사실적인 생태계 시뮬레이션 시스템으로 발전할 수 있는 견고한 출발점을 제공한다.
위 구현된 코드는 [여기]에서 확인할 수 있다.
Reference
[1] G. Datseris, A. R. Vahdati, and T. C. DuBois, “Agents.jl: A performant and feature-full agent based modelling software of minimal code complexity,” SIMULATION: Transactions of The Society for Modeling and Simulation International, vol. 98, no. 1, pp. 7-22, Jan. 2022, doi: 10.1177/00375497211068820.
[2] S. Railsback, D. Ayllón, U. Berger, V. Grimm, S. Lytinen, C. Sheppard, and J. Thiele, “Improving Execution Speed of Models Implemented in NetLogo,” Journal of Artificial Societies and Social Simulation, vol. 20, no. 1, p. 3, 2017, doi: 10.18564/jasss.3282.
[3] Unity Technologies, “Job system,” Unity Manual 6000.1. Accessed: Aug. 25, 2025. [Online]. Available: https://docs.unity3d.com/6000.1/Documentation/Manual/job-system-overview.html
[4] C. Gasch, J. M. Sotoca, M. Chover, I. Remolar, and C. Rebollo, “Procedural modeling of plant ecosystems maximizing vegetation cover,” Multimedia Tools and Applications, vol. 81, no. 12, pp. 16195-16217, May 2022, doi: 10.1007/s11042-022-12292-7.
[5] A. S. Joshi, “Reinforcement Learning-Enhanced Procedural Generation for Dynamic Narrative-Driven AR Experiences,” in Proc. 20th Int. Joint Conf. Comput. Vision, Imaging Comput. Graph. Theory Appl. (GRAPP), 2025, pp. 385-397, doi: 10.5220/0013373200003912.
[6] “Development of an agent-based ecosystem simulator for thousands of entities,” Final Degree Project, Universitat Politècnica de Catalunya (UPC), n.d.
[7] M. Iovino et al., “Comparison between Behavior Trees and Finite State Machines,” arXiv preprint arXiv:2405.16137, 2024.
[8] S. Snodgrass, “Levels from Sketches with Example-Driven Binary Space Partition,” in Proc. AAAI Conf. Artif. Intell. Interact. Digit. Entertain., vol. 15, no. 1, pp. 73-79, 2019, doi: 10.1609/aiide.v15i1.5227.