이 프로젝트는 수업 과제의 일환으로, 제공된 네트워크 프레임워크를 확장하여 클라이언트-서버 간 움직임 동기화, 입력 처리, 그리고 서버와 클라이언트 양쪽의 명령 송수신 시스템을 직접 구현했습니다. 실시간 멀티플레이 상호작용에 적합한 반응성 높고 모듈화된 설계를 구축하는데 중점을 두었습니다.
NetworkServerProcessing에서 호출되는 핵심 편의 함수를 제공하며 서버의 플레이어 상태를 관리합니다. 메시지를 직접 처리하지 않고, 연결된 플레이어 목록을 유지하며, 새로 접속한 클라이언트에 고유 seed를 할당하고, 연결, 연결 해제, 이동 같은 런타임 이벤트 갱신을 위한 데이터 조회를 지원합니다.
플레이어 등록, 제거, 조회를 위한 서버 측 함수를 제공합니다.
public class GameLogic : MonoBehaviour{ public int m_PlayerSeed = 1000; public List<PlayerData> m_ConnectedPlayers = new List<PlayerData>(); void Start() { NetworkServerProcessing.SetGameLogic(this); } public PlayerData Add(int clientConnectionID); public PlayerData Remove(int clientConnectionID); public PlayerData Search(int playerSeed);}
고유한 seed를 기준으로 플레이어를 찾아 반환합니다. 서버가 게임 플레이 중, 이동이나 입력을 갱신 및 적용할 때 사용됩니다.
2. NetworkServerProcessing 클래스
서버 측의 핵심 명령어 처리기 역할을 합니다. 이 정적 클래스는 연결된 클라이언트로부터 메시지를 받아 처리하고, 프로토콜 식별자를 분석하여 적절한 로직을 실행합니다. 연결, 연결 해제, 이동 같은 상태를 갱신하도록 GameLogic과 연계합니다.
프로토콜 메시지를 분석하고 경로를 지정하며 전달하는 중앙 관리 함수를 제공합니다.
static public class NetworkServerProcessing{ static public void ReceivedMessageFromClient(string msg, int clientConnectionID, TransportPipeline pipeline); static public void SendMessageToClient(string msg, int clientConnectionID, TransportPipeline pipeline); static public void ConnectionEvent(int clientConnectionID); static public void DisconnectionEvent(int clientConnectionID);}
핵심 함수
static public void ReceivedMessageFromClient(string msg, int clientConnectionID, TransportPipeline pipeline){ string[] csv = msg.Split(','); int signifier = int.Parse(csv[0]); switch (signifier) { case ClientToServerSignifiers.PTC_PLAYER_MOVE: { string seed = csv[1]; string posX = csv[2], posY = csv[3], posZ = csv[4]; // 서버 측 위치 데이터 업데이트 gameLogic.Search(int.Parse(seed))?.SetData(posX, posY, posZ); // 업데이트된 위치를 모든 연결된 클라이언트에 전달 string msgOut = $"{ServerToClientSignifiers.PTS_PLAYER_MOVE},{seed},{posX},{posY},{posZ}"; foreach (PlayerData data in gameLogic.m_ConnectedPlayers) SendMessageToClient(msgOut, data.m_ClientConnectionID, TransportPipeline.ReliableAndInOrder); } break; case ClientToServerSignifiers.PTC_PLAYER_MOVE2: // [생략] 위의 입력 기반 버전 break; }}
클라이언트로부터 수신된 메시지를 처리하고, 식별자를 분석해 실시간 서버 측 명령을 실행합니다. 세션 및 이동을 갱신 및 적용하기 위해 GameLogic과 연계합니다.
🎮 클라이언트 핵심 구성 요소
1. GameLogic 클래스
NetworkClientProcessing에서 호출되는 핵심 게임플레이 처리 함수를 제공하여 클라이언트에서 플레이어 객체 상태를 관리합니다. 메시지를 직접 분석하기보다는, 서버 지시에 따라 생성된 플레이어를 관리하고 위치를 갱신하며 연결 해제 시 제거하는 역할을 합니다.
플레이어의 생성, 동기화, 제거를 위한 클라이언트 측 함수를 제공합니다.
public class GameLogic : MonoBehaviour{ public Player m_prefabPlayer; public Player m_prefabOthers; public List<Player> m_ConnectedPlayers = new List<Player>(); void Start() { NetworkClientProcessing.SetGameLogic(this); } public void SpawnMySelf(int mySeed, Vector3 position); public void SpawnOthers(int otherSeed, Vector3 position); public void MovePlayer(int movedPlayerSeed, Vector3 targetPos); public void MovePlayer(int movedPlayerSeed, Vector3 targetPos, Vector2 inputKeys); public void OtherPlayerLeft(int leftPlayerSeed);}
클라이언트 측의 핵심 명령 처리기 역할을 합니다. 이 정적 클래스는 서버로부터 메시지를 받아 프로토콜 식별자를 분석하여 적절한 게임 로직을 실행합니다. 서버 기반 상태 변경에 맞춰 플레이어를 생성, 동기화, 제거하기 위해 GameLogic과 연계하여 동작합니다.
프로토콜 메시지를 분석하고 경로를 지정하며 전달하는 중앙 관리 함수를 제공합니다.
static public class NetworkClientProcessing{ static public void ReceivedMessageFromServer(string msg, TransportPipeline pipeline); static public void SendMessageToServer(string msg, TransportPipeline pipeline); static public void ConnectionEvent(); static public void DisconnectionEvent();}
핵심 함수
static public void ReceivedMessageFromServer(string msg, TransportPipeline pipeline){ string[] csv = msg.Split(','); int signifier = int.Parse(csv[0]); switch (signifier) { case ServerToClientSignifiers.PTS_CONNECTED_NEW_PLAYER: // [생략] 로컬 플레이어 초기화 및 생성 break; case ServerToClientSignifiers.PTS_CONNECTED_NEW_PLAYER_RECEIVE_DATA: // [생략] 서버에서 기존 플레이어 데이터를 받아 생성 break; case ServerToClientSignifiers.PTS_CONNECTED_PLAYERS_RECEIVE_NEW_PLAYER_DATA: // [생략] 다른 클라이언트에 새로 접속한 원격 플레이어 생성 break; case ServerToClientSignifiers.PTS_PLAYER_MOVE: // [생략] 원격 플레이어 위치 업데이트 (Type A) break; case ServerToClientSignifiers.PTS_PLAYER_MOVE2: // [생략] 원격 플레이어 위치 및 입력 업데이트 (Type B) break; case ServerToClientSignifiers.PTS_PLAYER_LEFT: // [생략] 연결이 끊긴 플레이어를 씬에서 제거 break; }}
서버로부터 수신된 메시지를 처리하고, 식별자를 분석해 클라이언트 측에 적용합니다. 생성, 이동, 플레이어 제거를 위해 GameLogic과 연계합니다.
이 프로젝트는 모듈화된 프로토콜 기반의 실시간 멀티플레이어 동기화 방식을 보여줍니다. 서버-클라이언트 간 로직을 일치시키고 명확한 메시지 처리 방식을 통해, 확장 가능하고 반응성이 뛰어난 플레이어 이동 시스템의 탄탄한 기반을 제공합니다. 또한 클라이언트-서버 구성과 실시간 게임 설계의 기본 개념에 대한 제 이해를 반영했습니다.