[Unity Dedicated Server] #4 - Client Side Prediction - Reconciliation

qweasfjbv·2026년 3월 5일

UnityServer

목록 보기
9/9

개요


저번 물리 연산에 이어서 Dedicated 서버를 통해 Server Authoritative 한 CSP 모델을 만들어 보겠습니다.

CSP를 구현하는 이유는 다음과 같습니다.

  • 클라이언트 상태를 그대로 받아오면 -> 치트 가능
  • 서버 상태를 그대로 받아오면 -> 입력 지연이 생김

따라서 클라이언트에서 먼저 예측해서 움직이기 + 서버 정보를 받으면 입력 정보들을 기반으로 재시뮬레이션하면 입력지연도 없앨 수 있고, 서버 정보를 토대로 다시 계산하기 때문에 치트도 방지할 수 있습니다.

구현


우선, 클라이언트 측에서 서버로 입력 정보를 보냅니다.

// PlayerController.Client.cs

private void Tick()
{
	///
    ///	Get Input, Simulate State, Predict ...
    ///
    
    // Send Input info to Server
	ServerManagers.Dedi.Send(null, Serializer.Serialize<PlayerInput>(PacketType.C2S_Input, input));
}

서버는 입력 정보를 토대로 게임의 정답 상태를 시뮬레이션 합니다.
해당 상태가 무조건 정답이 되며, 이를 통해 계산한 정보들만 신뢰할 수 있게 됩니다. (치트 방지)

// PlayerController.Server.cs

private void OnGetInput(IPEndPoint clientEP, PlayerInput input)
{
	// Simulate 
	curState = Simulate(curState, input, Time.fixedDeltaTime);

	curState.tick = input.tick;
	inputBuffer[input.tick] = input;
	stateBuffer[input.tick] = curState;
	ApplyState(curState);

	// Send "Correct" snapshot to Client
	ServerManagers.Dedi.Send(clientEP, Serializer.Serialize<PlayerState>(PacketType.S2C_Snapshot, curState));
}

다시 정답 상태를 클라이언트로 보내서 치팅을 방지하고 항상 옳은 상태를 유지할 수 있도록 합니다.


클라이언트 측에서 받는 정답 상태는 과거의 상태이므로, InputBuffer에 있는 정보들로 다시 재시뮬레이션을 해야합니다.

// PlayerController.Client.cs

private void OnGetSnapshot(PlayerState state)
{
	PlayerState simulateState = state;

	int tick = (state.tick + 1) % BUFFER_SIZE;

	while (tick != (currentTick + 1) % BUFFER_SIZE)
	{
		simulateState = Simulate(simulateState, inputBuffer[tick], TICK_DT);
		tick = (tick + 1) % BUFFER_SIZE;
	}

	Reconcile(simulateState);
	ApplyState(curState);
	stateBuffer[currentTick] = curState;
}

이렇게 하면 클라이언트 측에서 아무리 수치를 조작한다고해도, 항상 서버로부터 오는 정답 상태의 영향을 받게 됩니다.

아래는 서버가 없을 때와 있을 때의 테스트 영상입니다.

마무리


두 영상 모두 클라측에서 속도를 빠르게 조정했습니다.

위쪽에서는 서버를 무시하기 때문에 클라이언트가 임의로 조작한 대로 움직이는 반면에,
아래쪽에서는 서버의 정답을 받을 때마다 끊기면서 속도가 서버가 설정한대로 움직이게 되는 모습을 확인할 수 있었습니다.

이제 FPS 게임에 걸맞게 IK를 사용하여 사격 애니메이션을 만들고, 이후에 Lag Compensation까지 구현하여 Server Authoritative 하게 플레이어간 상호작용도 해결해보겠습니다.

0개의 댓글