🔥 Synchronizing states and inputs
Netcode for Entities 1.5.0v
Ghosts, Commands, RPC를 사용해 서버와 클라이언트 간 상태 및 입력 동기화합니다.
주제 | 설명 |
---|---|
1️⃣ Ghosts를 이용한 동기화 | 유령(Ghost)을 사용하면 서버와 클라이언트 간 상태를 일관되면서도 유연하게 동기화하고 복제할 수 있습니다. |
2️⃣ RPC(Remote Procedure Call)를 통한 통신 | 원격 프로시저 호출(RPC)은 게임의 상위 흐름 이벤트를 전달하거나 클라이언트에서 서버로 예측되지 않은 단발성 명령을 보낼 때 사용됩니다. |
3️⃣ Commands Stream을 통한 입력 처리 | 클라이언트는 이 인게임 상태로 설정되면 서버로 연속적인 Commands Stream을 보냅니다.이 Stream에는 모든 입력 정보와 마지막으로 수신한 스냅샷에 대한 확인 응답이 포함됩니다. |
1️⃣ Ghosts를 이용한 동기화
https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/synchronization.html
Ghosts를 사용하여 서버와 클라이언트 간 상태를 일관되고 커스터마이징 가능하게 동기화 및 복제하는 방법입니다.
주제 | 설명 |
---|---|
Ghosts and snapshots | Netcode for Entities에서 Ghost과 스냅샷(snapshot)이 무엇인지, 그리고 이를 멀티플레이어 프로젝트에서 상태 동기화에 어떻게 사용하는지를 이해합니다. |
GhostFieldAttribute 를 통한Serialization and synchronization | GhostFieldAttribute 를 사용하여 Unity.Entities.IComponentData 또는 Unity.Entities.IBufferElementData 의 어떤 필드와 속성이 서버에서 클라이언트로 직렬화 및 복제되어야 하는지를 지정합니다. |
GhostComponentAttribute 를 통한 복제 커스터마이징 | GhostComponentAttribute 와 그 속성들을 사용하여 런타임에서 복제가 어떻게 처리되는지를 커스터마이징할 수 있습니다. |
GhostComponentVariationAttribute로 복제 스키마 생성 | 를 사용하면 원본 타입이나 필드를 수정하지 않고도 특정 타입에 대해 (컴파일 타임에) 복제 스키마를 정의할 수 있습니다. |
Ghost 생성 및 미리 생성 | Ghost을 게임의 일환으로 생성한 후, 이들이 어떻게 동기화되어야 하는지를 정의한 뒤 Spawn합니다. |
Ghost type templates | Netcode for Entities는 고스트 컴포넌트 타입들이 베이킹(baking) 및 직렬화 과정에서 어떻게 처리될지를 정의하는 기본 템플릿을 제공합니다. 또한 사용자 정의 템플릿을 만들어 추가 타입을 등록할 수도 있습니다. |
Ghost groups | 고스트 그룹을 사용하여 여러 고스트 인스턴스 간의 복제 타이밍을 동기화하고, 일반적인 게임플레이 상태 오류를 방지할 수 있습니다. |
🔥 Ghosts and snapshots
https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/ghost-snapshots.html
Netcode for Entities에서 Ghosts
와 Snapshots
을 이해하고, 멀티플레이어 프로젝트에서 상태를 동기화하는 방법에 대한 내용입니다.
Netcode for Entities는 이벤트를 처리하기 위한 제한적인 형태의 원격 프로시저 호출(RPC) 기능도 지원합니다.
Ghost와 RPC 중 언제 어떤 기능을 사용할지에 대해서는 [RPC 비교]를 참고하세요.
✅ Ghosts
Ghost
는 멀티플레이어 게임에서 네트워크를 통해 동기화되는 오브젝트입니다.Ghost
는 서버가 소유하고 시뮬레이션합니다. 즉, 서버가 Ghost
에 대한 최종 권한(authority) 을 가지며, Ghost
를 생성, 제거, 업데이트할 수 있습니다.
서버에 연결된 각 클라이언트는 해당 Ghost
의 복사본을 가지며, 서버가 매 네트워크 틱마다 보내는 Snapshots
을 통해 해당 복사본을 업데이트합니다.
이 Snapshots
은 Ghost
상태의 일부를 포함합니다.
클라이언트는 Ghost
의 상태를 두 가지 타임라인(보간 또는 예측) 중 하나를 통해 게임 시뮬레이션에 반영하며, 이를 통해 부드러운 렌더링이 가능합니다.
중요한 점은, 클라이언트는 Ghost
를 직접 제어하거나 변경할 수 없습니다.
게임 시뮬레이션은 서버가 권한을 가지므로, 클라이언트가 Ghost
를 수정하더라도 이는 클라이언트 예측(Client Prediction) 으로 간주되며, 서버에서 보내는 새로운 Snapshots
에 의해 되돌려질 수 있습니다.
Ghost
를 생성할 때는 클라이언트와 서버 간 동기화 방식을 정의해야 합니다. 생성 후 Ghost
를 스폰하는 방법은 Ghost Spawning 페이지를 참고하세요.
✏️ Create a ghost
Unity 에디터에서 GhostAuthoringComponent가 포함된 프리팹을 생성하여 Ghost
를 만들 수 있습니다.
GhostAuthoringComponent는 프리팹의 동기화 방식을 구성할 수 있는 에디터 UI를 제공합니다. 다음과 같은 속성들을 설정해야 합니다:
- Name (이름)
- Importance (중요도)
- Supported Ghost Mode (지원되는 고스트 모드)
- Default Ghost Mode (기본 고스트 모드)
- Optimization Mode (최적화 모드)

또한 MaxSendRate 값을 설정하면 전체 대역폭 사용량을 줄일 수 있습니다.
Importance 값은 Snapshots
에 포함시킬 Ghost
를 선택할 때 우선 순위를 정하는 데 사용됩니다.
Snapshots
패킷의 크기는 설정으로 조정할 수 있습니다.
MaxSendRate (최대 전송 속도)는 해당 Ghost
프리팹 타입의 Ghost
Chunk가 초당 몇 회 전송될 수 있는지를 나타냅니다 (단위: Hz)
이는 전송 가능 최대 빈도를 의미할 뿐, 다른 요인들에 의해 제한될 수 있습니다.
예를 들어 아래와 같은 상황이 있다면
MaxSendRate가 100Hz인 경우, 기본 NetworkTickRate(60Hz)에 의해 60Hz로 제한됩니다.
MaxSendRate가 60Hz인데 NetworkTickRate가 30Hz인 경우, 30Hz가 최대 전송 속도입니다.
30Hz NetworkTickRate에 45Hz MaxSendRate를 설정하면, 실제 전송 속도는 30Hz로 내림(round down)됩니다.
✏️ Supported Ghost Mode options (지원되는 고스트 모드)
- All: 보간(Interpolated)과 예측(Predicted)을 모두 지원
- Interpolated: 보간만 지원
- Predicted: 예측만 지원
✏️ Default Ghost Mode (기본 고스트 모드)
- Interpolated: 서버에서 받은 모든
Ghost
를 보간 처리 - Predicted: 서버에서 받은 모든
Ghost
를 예측 처리 - Owner Predicted:
Ghost
의 소유 클라이언트에게는 예측 처리, 그 외 클라이언트에게는 보간 처리
이 모드를 사용하려면GhostOwner
컴포넌트를 추가하고, 코드에서NetworkId
필드를 설정해야 합니다.
✏️ Optimization Mode (최적화 모드)
- Dynamic: 상태가 변할 때와 변하지 않을 때 모두 작은 스냅샷 크기로 최적화
- Static: 상태가 변하지 않을 때는 전송하지 않고, 상태가 변할 때는 최적화되지 않음
✏️ Synchronize ghost components and fields
Ghost
에 어떤 컴포넌트와 필드를 동기화할지 지정하려면 C# 특성(Attribute)을 사용합니다.
속성 (Attribute) | 사용법 (Usage) | 추가 정보 (More information) |
---|---|---|
| 구조체의 필드나 속성에 GhostFieldAttribute 를 사용하여 어떤 컴포넌트(또는 버퍼) 필드를 직렬화할지 지정합니다. 어떤 컴포넌트든 하나 이상의 필드에 [GhostField] 가 지정되면, 해당 컴포넌트는 복제되어 고스트 데이터의 일부로 전송됩니다. | GhostFieldAttribute를 사용한 직렬화 및 동기화 |
| IEnableableComponent 구조체 정의에 GhostEnabledBitAttribute 를 사용하여 이 컴포넌트의 “활성화 비트(enabled bit)”도 직렬화해야 함을 지정합니다.이 속성이 지정되면 활성화 비트도 복제되어 고스트 데이터의 일부로 전송됩니다. | GhostComponentAttribute |
| ComponentType 구조체 정의에 GhostComponentAttribute 를 사용하여 다음을 선언합니다: – 어떤 프리팹 버전에 이 컴포넌트가 포함될지 – 자식 엔티티에 대해 이 컴포넌트를 직렬화할지 여부 – 어떤 클라이언트 하위 집합에 이 컴포넌트를 복제할지 ⚠️주의: GhostComponentAttribute 를 추가한다고 해서 컴포넌트의 필드가 자동으로 복제되지 않습니다. 각 필드에 GhostFieldAttribute 를 개별적으로 지정해야 합니다. | GhostComponentAttribute |
✅ Snapshots
Snapshots
은 특정 네트워크 틱에서 서버의 모든 Ghost
상태를 나타내는 표현입니다.
엔티티용 Netcode는 각 연결된 클라이언트에 틱당 한 번씩 Snapshots
을 전송하며, 이는
에 의해 정의된 속도로 이루어집니다(NetworkTickRate
와 다를 수 있음). SimulationTickRate
NetworkTickRate
가 SimulationTickRate
보다 낮을 경우, 엔티티용 Netcode는 연결의 하위 집합 그룹을 생성하고 하위 집합의 각 연결에 하나의 Snapshots
을 전송합니다.
그 후 다음 틱에서 다음 하위 집합에 Snapshots
을 전송하는 식으로 진행됩니다.
이는 GhostSendSystem
부하를 여러 SimulationTickRate
틱에 분산시키기 때문에 라운드 로빈 접근 방식이라고 합니다.
✏️ Snapshots 처리
Ghost
스냅샷 시스템은 서버에 존재하는 엔티티를 모든 클라이언트에 동기화합니다.
성능 향상을 위해 서버는 엔티티별이 아닌 Chunk별로 Ghost
를 처리합니다.
그러나 수신 클라이언트 측에서는 엔티티별로 처리가 이루어집니다.
서버의 한 Chunk에 있는 일련의 엔티티가 클라이언트의 한 Chunk에 있는 동일한 엔티티 집합과 일치하지 않을 수 있기 때문에 양쪽에서 Chunk별로 처리하는 것은 불가능합니다.
또한 각각 고유한 엔티티-Chunk 레이아웃을 가진 여러 클라이언트가 있습니다.
✏️ 부분 Snapshots
많은 Ghost
(또는 Ghost
데이터)를 복제할 때, 틱당 Snapshots
데이터 크기는 최대 전송 단위(MTU) 상한으로 제한됩니다.
그 결과, Snapshots
이 모든 Ghost
의 하위 집합만 포함하는 것은 일반적이고 예상된 일입니다.
이러한 Snapshots
을 부분 Snapshots
이라고 합니다.
중요도 값이 가장 높은 Chunk의 Ghost
가 먼저 추가되며, 엔티티용 Netcode는 거대한 패킷에 한 번에 모두 전송하는 대신 대규모 월드를 몇 개의 고스트 Chunk씩 스트리밍합니다.
이는 효과적으로 중요도 우선순위 큐입니다.
MaxSendRate
를 사용하여 각 스냅샷의 중요도 우선순위 큐의 일부로 간주되는 고스트 Chunk의 수를 줄일 수도 있으며, 이는 총 대역폭 소비를 줄일 수 있습니다.
Snapshots
의 최대 크기를 변경할 수 있습니다.
최대 크기를 줄이면 상대적인 헤더 오버헤드가 증가하고 사용 가능한 데이터가 줄어드는 대신 대역폭이 절약되며,
크기를 늘리면 Snapshots
당 여러 UDP 패킷을 전송해야 할 수 있어 패킷 손실 가능성이 증가할 수 있습니다.
자세한 내용은 중요도 스케일링(importance scaling)에 관한 문서를 참조하세요.
✏️ Snapshots 시각화 도구
네트워크를 통해 전송되는 내용을 이해하기 위해 Network Debugger 스냅샷 시각화 도구를 사용할 수 있습니다.
도구를 열려면 Multiplayer > Open NetDbg로 이동하면 브라우저 창에서 도구가 열립니다.
이 도구는 수신된 각 스냅샷에 대한 세로 막대를 표시하며, 각 스냅샷에 대한 주요 정보 분석을 제공합니다.


🔥 GhostFieldAttribute를 활용한 필드 동기화 및 직렬
https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/ghostfield-synchronize.html
또는 Unity.Entities.IComponentData
의 어떤 필드와 속성이 서버에서 클라이언트로 직렬화되고 복제될지 지정하려면 Unity.Entities.IBufferElementData
를 사용하세요.GhostFieldAttribute
컴포넌트나 버퍼에
로 주석이 달린 필드가 하나 이상 포함되면, 컴포넌트 직렬화를 구현하는 구조체가 자동으로 코드 생성됩니다.GhostFieldAttribute
외에도 GhostFieldAttribute
를 사용하여 런타임에서 복제가 처리되는 방식을 추가로 사용자 지정할 수 있습니다.GhostComponentAttribute
✅ GhostFieldAttribute 직렬화 사용자 지정
GhostFieldAttribute를 사용하여 컴포넌트와 버퍼의 직렬화를 사용자 지정하려면 다음 속성을 사용하세요.
자세한 내용은
API documentation를 참조하세요.GhostFieldAttribute
속성 (Property) | 기본값 (Default value) | 설명 (Description) |
---|---|---|
Quantization | float 타입은 기본적으로 비활성화됨, int 타입에서는 사용 불가 | Quantization 속성은 부동 소수점 숫자(및 다른 지원되는 타입, 예: 고스트 타입 템플릿)에 대해 정밀도를 제한하기 위한 quantization를 설정합니다. 부동 소수점 숫자는 지정된 양자화 값으로 곱해진 후 정수로 변환되어 대역폭을 절약합니다. |
Composite | 기본적으로 비활성화됨 | Composite 속성은 delta compression 시 비원시 타입(예: 구조체)의 변경 비트 마스크를 어떻게 계산할지를 제어합니다. true 로 설정하면, 구조체 전체에 변경 사항이 있을 경우 단 하나의 변경 비트만 생성됩니다. false 일 경우 각 필드마다 변경 비트를 가집니다. 예를 들어 GUID 와 같이 필드들이 함께 수정되는 경우에는 Composite=true 를 사용하는 것이 좋습니다. |
SendData | 기본적으로 활성화됨 | SendData 속성은 코드 생성 시 특정 필드를 직렬화 데이터에서 제외하도록 지정합니다. 구조체처럼 모든 필드가 기본적으로 직렬화되는 비원시 멤버에 유용합니다. |
Smoothing | 기본값은
| Smoothing 속성은 고스트가 GhostMode.Interpolated 모드일 때 필드가 어떻게 갱신될지를 제어합니다. 옵션은 다음과 같습니다: – Clamp : 스냅샷이 수신될 때마다 클라이언트 값을 최신 스냅샷 값으로 고정– Interpolate : 두 스냅샷 값 사이를 프레임마다 보간– InterpolateAndExtrapolate : 다음 틱에 대한 데이터가 없을 경우 이전 두 스냅샷 값을 기반으로 외삽 |
MaxSmoothingDistance | – | MaxSmoothingDistance 속성은 스냅샷 간 값 차이가 지정된 한계를 초과할 경우 보간을 비활성화합니다. 주로 텔레포트와 같은 상황에서 유용합니다. |
SubType | – | SubType 속성은 API를 사용하여 필드에 대해 사용자 지정 직렬화기를 지정할 때 사용합니다. |
⚠️ 참고
정적 최적화와 보간이 모두 표시된 고스트는 절대 외삽되지 않습니다.
정적 최적화된 고스트는 변경되지 않은 경우 스냅샷 업데이트를 전송하지 않기 때문에 ‘이 지속적으로 변화하는 값이 변화를 멈췄다’와 ‘아직 다음 연속 값을 받지 못했다’를 구별할 수 없습니다.
✏️ GhostField 상속
기본 타입이 아닌 필드 타입에 [GhostField]가 지정된 경우, 해당 속성(및 일부 속성)은 [GhostField]속성을 직접 구현하지 않는 모든 하위 필드에 자동으로 상속됩니다.
public struct Vector2 { public float x; [GhostField(Quantization=100)] public float y; } public struct MyComponent : IComponentData { //Value.x는 상위 정의에서 지정한 양자화 값(1000)을 상속합니다. //Value.y는 원래 양자화 값(100)을 유지합니다. [GhostField(Quantized=1000)] public Vector2 Value; }
참고- SubType 속성은 항상 기본값으로 재설정됩니다.
✅ Component serialization
Component serialization 및 복제용으로 표시하려면 전송하려는 값에 [GhostField] 속성을 추가하세요.
public struct MySerializedComponent : IComponentData { [GhostField]public int MyIntField; [GhostField(Quantization=1000)]public float MyFloatField; [GhostField(Quantization=1000, Smoothing=SmoothingAction.Interpolate)]public float2 Position; public float2 NonSerializedField; ... }
컴포넌트가 직렬화되려면 컴포넌트 자체가 public으로 선언되어야 합니다.
컴포넌트의 public 멤버만 직렬화될 수 있습니다. private 멤버에 [GhostField]를 추가해도 효과가 없습니다.
✅ Dynamic buffer serialization
버퍼를 직렬화 및 복제용으로 표시하려면 모든 public 필드에 [GhostField] 속성으로 주석을 달아야 합니다.
public struct SerialisedBuffer : IBufferElementData { [GhostField]public int Field0; [GhostField(Quantization=1000)]public float Field1; [GhostField(Quantization=1000)]public float2 Position; public float2 NonSerialisedField; // public 필드에 [GhostField]가 없으면 오류가 발생 // 명시적인 오류 private float2 NonSerialisedField; // 이것은 허용됩니다. 읽기 전에 클라이언트에서 이것을 설정해야 합니다. private이므로 직렬화 대상이 아닙니다. [GhostField(SendData=false)]public int NotSentAndUninitialised; // 이것은 허용됩니다. 읽기 전에 클라이언트에서 이것을 설정해야 합니다. ... }
버퍼가 직렬화되려면 버퍼 자체가 public으로 선언되어야 합니다.
버퍼의 public 멤버만 직렬화될 수 있습니다. private 멤버에 [GhostField]를 추가해도 효과가 없습니다.
필드의 직렬화 및 복제를 건너뛰려면 SendData property을 사용할 수 있습니다.
이는 다음을 의미합니다:
- 복제되지 않는 필드의 값은 절대 변경되지 않습니다.
- 새 버퍼 요소의 경우 그 내용이 기본값으로 설정되지 않으며 내용은 정의되지 않습니다(어떤 값이든 될 수 있음).
- 동적 버퍼 필드는 SmoothingAction을 지원하지 않으므로 버퍼에서는
GhostFieldAttribute.Smoothing
및GhostFieldAttribute.MaxSmoothingDistance
속성이 무시됩니다.
✅ ICommandData 및 IInputComponentData 직렬화
입력 필드에 [GhostField]를 주석으로 달아 서버에서 클라이언트로 복제할 수 있습니다.
이는 예를 들어 로컬 머신에서 다른 플레이어의 캐릭터 컨트롤러에 대한 클라이언트 측 예측을 활성화하는 데 유용할 수 있습니다.
IInputComponentData를 사용한 자동화된 입력 동기화 시:
public struct MyCommand : IInputComponentData { [GhostField] public int Value; }
ICommandData는 IBufferElementData의 하위 클래스이며 서버에서 클라이언트로의 복제를 위해 직렬화될 수 있습니다.
따라서 버퍼와 동일한 규칙이 적용됩니다: 명령 버퍼가 직렬화되려면 모든 필드에 주석이 달려 있어야 합니다.
ICommandData 사용 시:
[GhostComponent()] public struct MyCommand : ICommandData { [GhostField] public NetworkTick Tick {get; set;} [GhostField] public int Value; }
명령 데이터 직렬화는 원격 플레이어 예측을 구현하는 데 특히 유용합니다.
✅ 사용자 지정 타입에 대한 직렬화 지원 추가
GhostFieldAttribute
로 직렬화할 수 있는 타입은 템플릿을 통해 지정됩니다.
기본적으로 지원되는 타입 목록은 Ghost 타입 템플릿 페이지를 참조하세요.
기본 지원 타입 외에도 다음을 수행할 수 있습니다:
- 새 타입에 대한 자체 템플릿 추가
- 타입에 대한 사용자 지정 직렬화 템플릿을 제공하고
GhostFieldAttribute
의SubType
속성을 사용하여 대상 지정
템플릿 작성 및 사용 방법에 대한 자세한 내용은 템플릿 사용 및 작성 방법을 참조하세요.
✅ 추가 리소스
GhostFieldAttribute
로 직렬화할 수 있는 타입은 템플릿을 통해 지정됩니다.
GhostFieldAttribute
API documentationUnity.Entities.IComponentData
API documentationUnity.Entities.IBufferElementData
API documentation- Ghost types templates
- Ghost variants
- Customizing replication with
GhostComponentAttribute
🔥 GhostComponentAttribute를 사용한 복제 사용자 지정
https://docs.unity3d.com/Packages/com.unity.netcode@1.5/manual/ghostcomponentattribute.html
와 그 속성을 사용하여 런타임에서 복제가 처리되는 방식을 사용자 지정할 수 있습니다.GhostComponentAttribute
를 사용하기 전에 먼저 GhostComponentAttribute
GhostComponentAttribute
로 컴포넌트에 주석을 달아 직렬화 및 복제 대상으로 표시해야 합니다.
✅ GhostComponentAttribute 속성
를 사용하여 복제를 수정하는 방법을 사용자 지정하려면 다음 속성을 사용하세요. 자세한 내용은 GhostComponentAttribute
API 문서를 참조하세요.GhostComponentAttribute
속성 (Property) | 기본값 (Default value) | 설명 (Description) |
---|---|---|
OwnerSendType | All | OwnerSendType 속성은 ( 사용) 어떤 클라이언트 그룹에 구성 요소를 복제할지를 지정합니다. 예를 들어, 입력 명령을 자신의 플레이어에게만 복제하도록 설정할 수 있습니다. |
PrefabType | All | 속성은 ( 사용) 구성 요소가 어떤 프리팹 버전에서 사용 가능한지를 지정합니다. 예를 들어, 렌더링 관련 구성 요소를 서버 월드의 고스트 버전에서는 제거하는 데 사용할 수 있습니다. |
SendDataForChildEntity | false | SendDataForChildEntity 속성은 고스트 엔티티의 자식에 붙은 구성 요소를 복제할지를 지정합니다. 고스트 자식 엔티티의 복제는 부모보다 훨씬 느리므로 주의가 필요합니다. 이 속성은 [GhostEnabledBit]에도 적용됩니다. |
SendTypeOptimization | AllClients | 속성은 ( 사용) 고스트가 예측(predicted)인지 보간(interpolated)인지에 따라 구성 요소 복제를 제어합니다. 예를 들어, 실제로 고스트의 물리 상태를 예측할 때만 PhysicsVelocity 를 복제하도록 설정할 수 있습니다. |
[GhostComponent(PrefabType=GhostPrefabType.All, SendTypeOptimization=GhostSendType.OnlyInterpolatedClients, SendDataForChildEntity=false)] public struct MyComponent : IComponentData { [GhostField(Quantized=1000)] public float3 Value; }
✅ OwnerSendType 세부 정보
소유권에 기반하여 컴포넌트가 복제되는 클라이언트를 지정하려면 GhostComponentAttribute의 OwnerSendType 속성을 사용하세요.
OwnerSendType은 SendToOwnerType에 정의된 대로 다음 중 하나일 수 있습니다.
- None: 컴포넌트가 어떤 클라이언트에도 복제되지 않습니다.
- All: 컴포넌트가 모든 클라이언트에 복제됩니다.
- SendToOwner: 컴포넌트는 고스트를 소유한 클라이언트에만 복제됩니다.
- SendToNonOwner: 컴포넌트는 고스트를 소유한 클라이언트를 제외한 모든 클라이언트에 복제됩니다.
✅ PrefabType 세부 정보
컴포넌트가 사용 가능한 고스트 프리팹 버전을 지정하려면 GhostComponentAttribute의 PrefabType 속성을 사용하세요.
PrefabType은 GhostPrefabType에 정의된 대로 다음 중 하나일 수 있습니다.
- None: 컴포넌트가 어떤 고스트 프리팹 유형에서도 사용할 수 없습니다.
- All: 컴포넌트가 서버와 모든 클라이언트에서 사용 가능합니다.
- Server: 컴포넌트는 서버에서만 사용 가능합니다.
- Client: 고스트가 예측되든 보간되든 관계없이 컴포넌트는 클라이언트에서만 사용 가능합니다.
- AllPredicted: 컴포넌트는 서버와 고스트가 예측되는 클라이언트에서 사용 가능합니다.
- PredictedClient: 컴포넌트는 고스트가 예측되는 클라이언트에서만 사용 가능합니다.
- InterpolatedClient: 컴포넌트는 고스트가 보간되는 클라이언트에서만 사용 가능합니다.
예를 들어, RenderMesh에 [GhostComponent(PrefabType=GhostPrefabType.Client)]를 추가하면 고스트는 서버 월드에 인스턴스화될 때 RenderMesh를 가지지 않지만 클라이언트 월드에 인스턴스화될 때는 가지게 됩니다.
⚠️참고
따라서 런타임 예측 전환은 예측 모드가 변경됨에 따라 고스트에서 라이브로 컴포넌트를 추가하고 제거할 수 있는 가능성이 있습니다.
✅ SendDataForChildEntity 세부 정보
컴포넌트가 고스트 엔터티의 자식에 연결된 경우 복제할지 여부를 지정하려면 GhostComponentAttribute의 SendDataForChildEntity 속성을 사용하세요.
자식 엔터티를 직렬화하고 복제하는 것은 계산 비용이 많이 드므로 이 속성의 기본값은 false입니다.
✅ SendTypeOptimization 세부 정보
고스트가 해당 클라이언트에서 보간되거나 예측되는지에 따라 컴포넌트가 복제되는 클라이언트를 지정하려면 GhostComponentAttribute의 SendTypeOptimization 속성을 사용하세요.
SendTypeOptimization은 GhostSendType에 정의된 대로 다음 중 하나일 수 있습니다.
- DontSend: 컴포넌트가 어떤 클라이언트에도 복제되지 않습니다. 엔티티용 Netcode는 데이터를 수신하지 않는 클라이언트에서 컴포넌트를 수정하지 않습니다.
- AllClients: 컴포넌트가 모든 클라이언트에 복제됩니다.
- OnlyPredictedClients: 컴포넌트는 고스트를 예측하는 클라이언트에만 복제됩니다.
- OnlyInterpolatedClients: 컴포넌트는 고스트를 보간하는 클라이언트에만 복제됩니다.
⚠️참고
SendTypeOptimization 및/또는 OwnerSendType을 설정하여 컴포넌트를 복제해야 하는 클라이언트 유형을 지정해도 프리팹의 컴포넌트 존재에는 영향을 미치지 않으며, 데이터를 수신하지 않은 클라이언트의 컴포넌트를 수정하지도 않습니다.