공간 분할 최적화
GridSpatialization2D 설정 및 최적화 전략
GridSpatialization2D 설정
2D 그리드 기반 공간 분할 노드
void UMyReplicationGraph::InitGlobalGraphNodes()
{
Super::InitGlobalGraphNodes();
// 2D 그리드 공간 분할 노드 생성
GridNode = CreateNewNode<UReplicationGraphNode_GridSpatialization2D>();
// 그리드 설정
GridNode->CellSize = 10000.f; // 100m x 100m 셀
GridNode->SpatialBias = FVector2D(-WORLD_MAX, -WORLD_MAX);
// 월드 경계 설정 (선택적)
GridNode->SetBiasAndGridBounds(
FVector2D(-50000.f, -50000.f), // Bias
FBox2D(
FVector2D(-50000.f, -50000.f),
FVector2D(50000.f, 50000.f)) // Bounds
);
AddGlobalGraphNode(GridNode);
}
| 설정 | 권장값 | 설명 |
|---|---|---|
| CellSize | 10000 (100m) | 그리드 셀 크기, 너무 작으면 오버헤드 증가 |
| SpatialBias | 월드 원점 | 그리드 시작 위치 |
| ConnectionNetCullDistance | 15000 (150m) | 기본 네트워크 컬링 거리 |
클래스별 설정
Actor 타입에 따른 네트워크 설정
void UMyReplicationGraph::InitGlobalActorClassSettings()
{
Super::InitGlobalActorClassSettings();
// 모든 Actor에 대한 기본 설정
for (TObjectIterator<UClass> It; It; ++It)
{
UClass* Class = *It;
if (!Class->IsChildOf(AActor::StaticClass()))
continue;
FClassReplicationInfo ClassInfo;
// PlayerState: 항상 관련
if (Class->IsChildOf(APlayerState::StaticClass()))
{
ClassInfo.ReplicationPeriodFrame = 1;
}
// Projectile: 높은 업데이트 빈도
else if (Class->IsChildOf(AProjectile::StaticClass()))
{
ClassInfo.ReplicationPeriodFrame = 1;
ClassInfo.CullDistanceSquared = 10000.f * 10000.f;
}
// 환경 오브젝트: 낮은 빈도
else if (Class->IsChildOf(AEnvironmentActor::StaticClass()))
{
ClassInfo.ReplicationPeriodFrame = 4; // 4프레임마다
}
GlobalActorReplicationInfoMap.SetClassInfo(Class, ClassInfo);
}
}
Cull Distance 전략
거리 기반 복제 제어
- 플레이어 캐릭터 - 150m (항상 보여야 함)
- NPC/적 - 100m (전투 범위)
- 아이템 - 50m (상호작용 범위)
- 환경 오브젝트 - 30m (배경 요소)
Cull Distance가 렌더링 거리보다 작으면 Actor가 갑자기 나타나거나 사라지는 현상이 발생합니다. 렌더링 LOD와 네트워크 Cull Distance를 조율하세요.
동적 공간 분할 최적화
런타임 그리드 튜닝과 디버깅
Actor별 CullDistance 오버라이드
void UMyReplicationGraph::InitGlobalActorClassSettings()
{
Super::InitGlobalActorClassSettings();
// 보스 몬스터: 먼 거리에서도 복제
FClassReplicationInfo BossInfo;
BossInfo.CullDistanceSquared = 50000.f * 50000.f;
BossInfo.ReplicationPeriodFrame = 1;
GlobalActorReplicationInfoMap.SetClassInfo(
ABossMonster::StaticClass(), BossInfo);
// 드롭 아이템: 가까운 거리만
FClassReplicationInfo ItemInfo;
ItemInfo.CullDistanceSquared = 3000.f * 3000.f;
ItemInfo.ReplicationPeriodFrame = 3;
GlobalActorReplicationInfoMap.SetClassInfo(
ADroppedItem::StaticClass(), ItemInfo);
}
콘솔 명령어 Net.RepGraph.DrawCellBounds 1로 그리드 셀 경계를 시각화할 수 있습니다. Net.RepGraph.LogActorRemove 1로 Actor 제거 로그를 확인하세요.
- 10,000 (100m) - 일반 슈터/RPG, 중밀도 Actor 분포
- 20,000 (200m) - 오픈월드, 넓은 시야 범위
- 5,000 (50m) - 밀집 도시 맵, 빌딩 내부 전투
핵심 요약
- GridSpatialization2D - 2D 그리드로 월드 분할, 인접 셀만 복제
- CellSize - 100m 권장, 너무 작으면 오버헤드
- ReplicationPeriodFrame - 클래스별 업데이트 빈도 조절
- CullDistanceSquared - 거리 기반 복제 컬링
도전 과제
배운 내용을 직접 실습해보세요
InitGlobalActorClassSettings에서 ACharacter, AProjectile, APickupItem 각각에 서로 다른 CullDistanceSquared와 ReplicationPeriodFrame을 설정하고, Net.RepGraph.DrawCellBounds로 시각화하여 결과를 확인해보세요.
CellSize를 5000, 10000, 20000으로 변경하며 stat net 명령어로 대역폭과 서버 CPU 사용량을 비교해보세요. 50명 플레이어 시뮬레이션에서 최적 값을 찾아보세요.
오픈월드 맵에서 실내/실외 영역별로 다른 CellSize를 적용하는 하이브리드 공간 분할 시스템을 설계하세요. GridSpatialization2D 노드를 2개 생성하고 RouteAddNetworkActorToNodes에서 Actor 위치에 따라 분배하는 방식을 구현해보세요.