PART 1 - 강의 2/4

Actor Channel 시스템

UActorChannel, Bunch 구조, Initial Spawn Bunch 상세 분석

01

UActorChannel 개요

Actor 복제의 핵심 채널

핵심 개념

UActorChannel은 Actor와 그 서브오브젝트의 프로퍼티 변경 및 RPC 교환을 담당하는 채널입니다. 각 복제되는 Actor마다 하나의 ActorChannel이 생성됩니다.

C++ // 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() (컴포넌트 복제)
02

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 (서버가 할당)
주의: GUID 불일치

Static Actor의 NetGUID는 패키지 경로로 계산됩니다. 서버와 클라이언트의 레벨 버전이 다르면 GUID 불일치로 Actor 매핑이 실패할 수 있습니다.

03

FObjectReplicator

오브젝트 복제의 실제 작업자

C++ // FObjectReplicator: 개별 오브젝트의 복제 담당 class FObjectReplicator { // 복제 대상 오브젝트 TWeakObjectPtr<UObject> Object; // 복제 레이아웃 (프로퍼티 메타데이터) TSharedPtr<FRepLayout> RepLayout; // 변경된 프로퍼티 추적 TArray<uint16> LifetimeCustomDeltaProperties; // 프로퍼티 비교 및 전송 bool ReplicateProperties( FOutBunch& Bunch, FReplicationFlags RepFlags); };

변경 감지 메커니즘

  • Recent 버퍼 - 마지막으로 전송된 프로퍼티 값 저장
  • 비교 - 현재 값과 Recent 버퍼 비교
  • 전송 - 변경된 프로퍼티만 Bunch에 추가
  • 업데이트 - ACK 수신 후 Recent 버퍼 갱신
04

서브오브젝트 복제

컴포넌트와 UObject 서브오브젝트 복제

Registered Subobject List (UE5 권장)

C++ // 생성자에서 활성화 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); }
Iris 호환성

Registered Subobject List는 Iris Replication System에서 필수입니다. ReplicateSubobjects() 오버라이드 방식은 Iris에서 지원되지 않습니다.

SUMMARY

핵심 요약

  • UActorChannel - 각 복제 Actor당 하나씩 생성, ReplicateActor()로 복제 수행
  • Initial Spawn Bunch - Actor 생성 시 클래스, 위치, NetGUID, 초기 프로퍼티 전송
  • NetGUID - Static(레벨 배치)과 Dynamic(런타임 스폰)으로 구분
  • FObjectReplicator - Recent 버퍼로 변경 감지, 변경분만 전송
  • Registered Subobject List - UE5 권장 방식, Iris 필수
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: Registered Subobject List 사용

bReplicateUsingRegisteredSubObjectList = true로 설정하고, ReadyForReplication()에서 AddReplicatedSubObject()로 커스텀 UActorComponent를 등록하세요. 서브오브젝트의 UPROPERTY(Replicated) 값이 클라이언트에 정상 전달되는지 확인하세요.

실습 2: NetGUID 디버깅

log LogNetPackageMap Verbose 명령어로 Actor의 NetGUID 할당을 관찰하세요. 레벨에 배치된 Static Actor와 SpawnActor로 생성한 Dynamic Actor의 GUID 범위 차이를 확인해보세요.

심화 과제

동적으로 서브오브젝트를 추가/제거하는 인벤토리 시스템을 구현하세요. AddReplicatedSubObject와 RemoveReplicatedSubObject를 사용하여 무기 장착/해제 시 서브오브젝트를 관리하고, 클라이언트에서 올바르게 동기화되는지 테스트하세요.