포스트

개발일지 #02 - SyncEnum 제네릭 상태 동기화 구현

FishNet 커스텀 제네릭 상태 동기화(SyncEnum) 구현

개발일지 #02 - SyncEnum 제네릭 상태 동기화 구현

오늘의 작업 내용

원래는 플레이어 움직임 동기화 작업을 진행할 예정이었으나, 상태 기반으로 시스템을 구성하는 것이 더 효율적일 것 같아서 우선순위를 변경했다. 커스텀 제네릭 상태 동기화 타입 SyncEnum<TEnum>을 구현하고 프로젝트에 적용했다. 이후 모든 시스템에서 범용적으로 사용할 수 있는 기반 클래스를 만들었다.

구현 배경

  • 과거 멀티플레이 프로젝트에서 플레이어/적/스테이지 등 여러 시스템들에 대해서 각 상태별 클래스를 만들어 관리했었다.
  • Photon Fusion에서는 유사 목적의 상위 수준 유틸이 제공되지만, FishNet은 로우 레벨 커스터마이징을 권장한다.
  • 동일한 패턴의 상태 동기화를 개별 클래스로 반복 구현하는 대신, 열거형을 제네릭으로 받는 공통 SyncType으로 정규화했다.

설계 요점

  • ICustomSync 상속: FishNet 커스텀 동기화 타입으로 인식되도록 SyncBase, ICustomSync를 기반으로 설계.
  • 서버 권한 모델: 값 변경은 서버에서만 허용. 비서버에서 시도 시 경고 후 중단.
  • 직렬화 전략: 열거형을 int로 직렬화(WriteInt32/ReadInt32).
  • 동기화 흐름:
    • 변경 시 Dirty() -> 틱에 WriteDelta로 전송
    • 초기 동기화 시 WriteFull 전송(변경 이력이 있을 때)
    • 수신 측은 Read에서 canModifyValuesnewChangeId로 적용/이벤트 제어

공개 API 요약

  • **SyncEnum**: `where TEnum : struct, System.Enum`
    • TEnum Value : 현재 값
    • void ServerSetValue(TEnum next) : 서버 전용 값 변경(Dirty 포함)
    • event EnumChanged OnChange : (prev, next, asServer) 콜백

사용 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private readonly SyncEnum<E_PlayerState> _playerState = new();

public override void OnStartServer()
{
    base.OnStartServer();
    _playerState.OnChange += (prev, next, asServer) =>
    {
        // 중요 분기만 간단 처리
    };
}

public void SetPlayerState(E_PlayerState state)
{
    if (IsServerStarted == true)
    {
        _playerState.ServerSetValue(state);
    }
}

적용 효과

  • 재사용성: 플레이어/적/스테이지 등 다양한 열거형 상태를 단일 타입으로 동기화.
  • 일관성: 서버 권한/델타·풀 전송/이벤트 패턴을 표준화.
  • 확장성: 새 열거형이 추가되어도 타입 인자만 바꾸면 즉시 적용 가능.

다음 단계

  • 플레이어 움직임 동기화: SyncEnum<E_PlayerState>를 활용한 상태 기반 이동/애니메이션 처리
  • 적 AI 상태 관리: SyncEnum<E_EnemyState>로 적 행동 패턴 동기화
  • 게임 스테이지 로직: SyncEnum<E_GamePhase>를 통한 라운드/페이즈 관리
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.