Actor Channel 시스템
UActorChannel, Bunch 구조, Initial Spawn Bunch 상세 분석
UActorChannel 개요
Actor 복제의 핵심 채널
UActorChannel은 Actor와 그 서브오브젝트의 프로퍼티 변경 및 RPC 교환을 담당하는 채널입니다. 각 복제되는 Actor마다 하나의 ActorChannel이 생성됩니다.
// UActorChannel 주요 메서드
class UActorChannel : public UChannel
{
// Actor 복제의 핵심 메서드
virtual bool ReplicateActor();
// 최근 전송된 프로퍼티 상태 추적
TArray<uint8> Recent; // Atomic 프로퍼티용 (int, float, object*)
TMap<int32, void*> RecentDynamicState; // Dynamic 프로퍼티용 (TArray)
// Actor 채널 생성/파괴
virtual void SetChannelActor(AActor* InActor);
virtual void Close();
};
ReplicateActor 호출 흐름
UNetDriver::ServerReplicateActors()
+-- ConsiderList 구성 (관련 Actor 수집)
+-- PrioritizeActors() (우선순위 정렬)
+-- 각 Actor에 대해:
+-- UActorChannel::ReplicateActor()
+-- ReplicateProperties() (변경된 프로퍼티 전송)
+-- ReplicateSubobjects() (컴포넌트 복제)
Initial Spawn Bunch
Actor 생성 시 전송되는 초기 데이터
[Initial Spawn Bunch]
+-- SpawnInfo (ActorChannel에서 생성)
| +-- Actor Class
| +-- Spawn Location/Rotation
| +-- Actor NetGUID
| +-- Component NetGUIDs
+-- Content Chunks (각 FObjectReplicator에서 생성)
+-- Initial Properties
+-- Replicated Components
NetGUID 시스템
NetGUID는 네트워크 상에서 오브젝트를 고유하게 식별하는 32비트 값입니다.
| 타입 | 범위 | 설명 |
|---|---|---|
| Static | 1 ~ 0x3FFFFFFF | 레벨에 배치된 Actor (패키지 경로로 결정) |
| Dynamic | 0x40000000+ | 런타임에 스폰된 Actor (서버가 할당) |
Static Actor의 NetGUID는 패키지 경로로 계산됩니다. 서버와 클라이언트의 레벨 버전이 다르면 GUID 불일치로 Actor 매핑이 실패할 수 있습니다.
FObjectReplicator
오브젝트 복제의 실제 작업자
// FObjectReplicator: 개별 오브젝트의 복제 담당
class FObjectReplicator
{
// 복제 대상 오브젝트
TWeakObjectPtr<UObject> Object;
// 복제 레이아웃 (프로퍼티 메타데이터)
TSharedPtr<FRepLayout> RepLayout;
// 변경된 프로퍼티 추적
TArray<uint16> LifetimeCustomDeltaProperties;
// 프로퍼티 비교 및 전송
bool ReplicateProperties(
FOutBunch& Bunch,
FReplicationFlags RepFlags);
};
변경 감지 메커니즘
- Recent 버퍼 - 마지막으로 전송된 프로퍼티 값 저장
- 비교 - 현재 값과 Recent 버퍼 비교
- 전송 - 변경된 프로퍼티만 Bunch에 추가
- 업데이트 - ACK 수신 후 Recent 버퍼 갱신
서브오브젝트 복제
컴포넌트와 UObject 서브오브젝트 복제
Registered Subobject List (UE5 권장)
// 생성자에서 활성화
AMyActor::AMyActor()
{
// 새로운 서브오브젝트 등록 방식 활성화
bReplicateUsingRegisteredSubObjectList = true;
// 컴포넌트 생성
InventoryComponent = CreateDefaultSubobject<UInventoryComponent>(
TEXT("Inventory"));
}
// ReadyForReplication에서 등록
void AMyActor::ReadyForReplication()
{
Super::ReadyForReplication();
// 서브오브젝트 등록
AddReplicatedSubObject(InventoryComponent);
}
// 동적 추가/제거
void AMyActor::AddWeapon(UWeapon* Weapon)
{
AddReplicatedSubObject(Weapon);
}
void AMyActor::RemoveWeapon(UWeapon* Weapon)
{
RemoveReplicatedSubObject(Weapon);
}
Registered Subobject List는 Iris Replication System에서 필수입니다. ReplicateSubobjects() 오버라이드 방식은 Iris에서 지원되지 않습니다.
핵심 요약
- UActorChannel - 각 복제 Actor당 하나씩 생성, ReplicateActor()로 복제 수행
- Initial Spawn Bunch - Actor 생성 시 클래스, 위치, NetGUID, 초기 프로퍼티 전송
- NetGUID - Static(레벨 배치)과 Dynamic(런타임 스폰)으로 구분
- FObjectReplicator - Recent 버퍼로 변경 감지, 변경분만 전송
- Registered Subobject List - UE5 권장 방식, Iris 필수
도전 과제
배운 내용을 직접 실습해보세요
bReplicateUsingRegisteredSubObjectList = true로 설정하고, ReadyForReplication()에서 AddReplicatedSubObject()로 커스텀 UActorComponent를 등록하세요. 서브오브젝트의 UPROPERTY(Replicated) 값이 클라이언트에 정상 전달되는지 확인하세요.
log LogNetPackageMap Verbose 명령어로 Actor의 NetGUID 할당을 관찰하세요. 레벨에 배치된 Static Actor와 SpawnActor로 생성한 Dynamic Actor의 GUID 범위 차이를 확인해보세요.
동적으로 서브오브젝트를 추가/제거하는 인벤토리 시스템을 구현하세요. AddReplicatedSubObject와 RemoveReplicatedSubObject를 사용하여 무기 장착/해제 시 서브오브젝트를 관리하고, 클라이언트에서 올바르게 동기화되는지 테스트하세요.