Paint War에서는 여러 플레이어가 같은 타일을 동시에 칠할 수 있습니다. 만약 각 클라이언트가 타일의 최종 소유자를 직접 확정한다면 서로 다른 화면을 볼 수 있기 때문에, 타일 소유권을 서버 기준으로 관리했습니다.
1. 입력 요청과 결과 확정을 구분하기
플레이어가 타일 위로 움직이거나 스킬을 사용했다고 해서 해당 클라이언트의 소유권 데이터가 곧 최종 결과가 되는 것은 아닙니다.
NetworkTilePaintAuthority에서는 클라이언트가 TileClaimRequestBroadcast로 좌표와 요청 소유자를 전송하고, 서버가 실제 타일 상태를 변경한 뒤 그 결과를 공유하도록 했습니다.
public struct TileClaimRequestBroadcast : IBroadcast
{
public int X;
public int Y;
public int Owner;
public byte NeutralOnly;
}
요청은 이 타일을 칠하고 싶다는 의미이고, 방송되는 결과는 실제로 누가 소유하게 되었는가라는 의미입니다. 서버에서는 범위, 파괴 여부, 영토 규칙 등을 고려해 점령을 처리합니다.
2. 타일마다 매번 패킷을 보내지 않기
연속 이동과 광역 스킬에서는 짧은 시간에 많은 타일의 소유자가 바뀔 수 있습니다. 이를 매번 독립된 방송으로 보낸다면 전송 횟수가 늘어나므로 변경을 잠시 모아서 보냅니다.
private readonly Dictionary<Vector2Int, PaintOwner> pendingTileChanges
= new();
private void BroadcastTileOwner(Vector2Int index, PaintOwner owner)
{
pendingTileChanges[index] = owner;
enabled = true;
}
Dictionary를 사용해 같은 타일의 변경이 여러 번 발생하면 마지막 소유자만 남깁니다. FlushPendingTileChanges()는 이 데이터를 TileOwnerDelta[]로 바꾼 뒤 TileOwnerBatchBroadcast 하나에 담아 전송합니다.
기본 코드의 tileBatchInterval은 0.05f로 설정되어 있습니다. 이는 타일마다 개별 전송하는 것보다 방송 횟수를 줄이는 구조이지만, 실제 네트워크 사용량 감소율은 별도로 측정하지 않았으므로 수치로 단정하지 않겠습니다.
3. 뒤늦게 들어온 플레이어는 전체 상태가 필요합니다
변경된 타일만 방송하는 방식에는 한계가 있습니다. 게임 중간에 접속한 플레이어는 앞서 발생한 변경 내역을 받지 못했기 때문입니다.
그래서 TileGridSnapshotBroadcast에 그리드 크기, 소유자 배열, 파괴된 타일 배열을 담고, 초기 진입이나 라운드 리셋 시 전체 상태를 전송하도록 했습니다. 아직 타일 맵이 준비되지 않은 클라이언트는 맵이 준비된 이후 스냅샷을 다시 요청합니다.
즉 기존 참가자에게는 변경분(delta)을 보내고, 새 참가자에게는 전체 스냅샷(snapshot)을 제공하는 방식입니다.
4. 타일 데이터와 화면 표시도 분리하기
실제 소유자 배열은 TileGridState, 영토 연결 여부는 ConnectedTerritoryState, 화면 표시 관련 처리는 TilePaintView가 맡습니다. 그 위에서 TilePaintManager가 공통 API를 제공하는 구조입니다.
이렇게 구분해 두면 네트워크 응답을 적용하거나 맵을 초기화할 때도 같은 타일 데이터를 기준으로 처리할 수 있습니다.
정리
4인 멀티플레이에서 중요한 것은 빠르게 색을 바꾸는 것만이 아니라 누가 최종 상태를 결정하는지입니다. 서버 권한으로 결과를 확정하고, 빈번한 변화는 묶어서 보내며, 늦게 입장한 참가자는 스냅샷으로 상태를 복구하도록 설계했습니다.
참고한 구현 코드
'Project > PaintWar' 카테고리의 다른 글
| [Unity Mobile] 조이스틱 방향 떨림과 격자 코너 통과 문제 해결 (0) | 2026.08.29 |
|---|---|
| [Unity Multiplayer] 격자 텔레포트와 이동 경로 위 폭탄 탈취 구현 (0) | 2026.08.29 |
| [Unity] 무기마다 다른 범위를 데이터와 패턴으로 분리하기 (0) | 2026.08.29 |
| [Unity AI] 가까운 타일만 따라가던 Bot이 전황을 읽게 만들기 (0) | 2026.08.29 |
| [Unity] 본진과 연결된 영토만 점수로 인정하기 — BFS와 고립 복구 (0) | 2026.08.29 |