-
스파르타) The Last Rollback (D-26, Node.js 게임 서버 최종 프로젝트)TIL-sparta 2024. 8. 1. 22:47
> 과제 진행 간 완료한 사항 및 문제점과 해결 과정을 정리해보았다.학습 키워드: Node.js, C#, Unity
1. 완료한 과제 진행 사항
1) 던전 위치 동기화 수정 및 낮/밤 라운드 기반 구조 작성:
- 상세 작업 내용은 위 PR에 연결된 Issue 참고
2. 과제 진행 간 문제점
1) 같은 던전 세션의 다른 캐릭터가 표시되지 않던 문제 (해결):
던전 입장 시 먼저 입장한 캐릭터의 클라이언트에서 나중에 입장한 캐릭터가 보이지 않는 문제가 있었다. 팀원들과 같이 원인을 찾아봐도 답이 나오지 않아서 보류하고 Issue #49 의 작업을 진행, enter-dungeon.js 코드에서 비효율적인 구조를 찾게되어서 수정했다.
그런데 수정 이후부터 양 쪽 클라이언트에서 정상적으로 모든 유저가 표시되었다.
정확한 원인은 알 수 없으나 캐릭터 정보를 불러와 패킷에 담는 과정에서 데이터가 꼬인 듯 싶다.+ 24-08-28 추가: 커밋을 찾아서 다시 조사해보니 기존 코드의 문제점을 바로 알 수 있었다.
// match_queue.js (기존 코드) ... for (const accountId of accountIds) { // 각 유저의 town session 내 다른 유저에게 Despawn 패킷 전송 const townSession = getTownSessionByUserId(accountId); townSession.removeUser(accountId); // users의 유저를 battle session에 추가 // redis const playerInfo = await townRedis.getPlayerInfo(accountId); await dungeonRedis.createGuest(playerInfo, hostId, accountId); // 인메모리 const user = getUserById(accountId); dungeonSession.addUser(user); // town session에서 유저 제거 await townRedis.removePlayer(accountId, false); // 각 클라이언트에게 S_EnterDungeon 패킷 전송 enterDungeonSession(accountId, dungeonCode); } } };
기존 코드에서는 for 루프를 돌면서 던전에 유저를 추가하고 패킷을 전송했는데, 이렇게 되면 보내는 순서에 따라 먼저 추가된 유저에게서 나머지 유저의 위치 정보를 받을 수 없는 현상이 나타나게 된다. 이후 고쳤던 부분이 루프 맨 아래의 enterDungeonSession 인데, 원래 구조에서 동일한 데이터를 가져오는 I/O 작업이 반복적으로 이루어지는 것을 발견해서 루프의 바깥으로 빼놓는 과정을 거쳤다. 이로 인해 모든 유저가 추가된 이후 패킷을 보내는 방식으로 자연스럽게 바뀌게되어 문제가 해결된 것이다.
// match_queue.js (바뀐 코드) ... for (const accountId of accountIds) { // 각 유저의 town session 내 다른 유저에게 Despawn 패킷 전송 const townSession = getTownSessionByUserId(accountId); townSession.removeUser(accountId); // users의 유저를 battle session에 추가 // redis // const playerInfo = await townRedis.getPlayerInfo(accountId); // await dungeonRedis.createGuest(playerInfo, hostId, accountId); // 인메모리 const user = getUserById(accountId); dungeonSession.addUser(user); // town session에서 유저 제거 await townRedis.removePlayer(accountId, false); // 각 클라이언트에게 S_EnterDungeon 패킷 전송 // enterDungeonSession(accountId, dungeonCode); } enterDungeonSession(dungeonSession, dungeonCode); } };
enterDungeonSession 코드는 기존에 한 명의 유저에게만 패킷을 보내고 있었는데, 이 부분에 for loop를 추가하여 모든 유저가 참가한 이후의 정보를 보내줄 수 있도록 변경했다. 자세한 내용은 위 커밋의 enter-dungeon.js 파일을 참고하자.
--
이후에 위치 정보 패킷을 주고 받는 과정에서 패킷은 정상적으로 들어오는데 캐릭터는 움직이지 않는 이슈가 있었으나, 단순히 Update() 의 조건문에 걸려서 코드가 실행되지 않고 있는 문제였다.
public void Spawn (PlayerInfo playerInfo, bool mine) { var tr = playerInfo.Transform; var spawnPos = spawnArea.position; spawnPos.x += tr.PosX; spawnPos.z += tr.PosZ; if (mine) { myPlayer = CreatePlayer(playerInfo, spawnPos); myPlayer.SetIsMine(true); foreach (Monster monster in monsterObjs) { monster.destinations.Add(myPlayer.transform); } } else { CreatePlayer(playerInfo, spawnPos).SetIsMine(false); // SetIsMine 추가 } }
SetIsMine 함수가 캐릭터의 init 상태를 세팅해주고 있어서 자신의 캐릭터가 아니어도 false 값으로 콜해줘야만 동기화가 진행된다.
--
REFERENCES:> 프로젝트 repo
728x90'TIL-sparta' 카테고리의 다른 글
스파르타) The Last Rollback (D-24, Node.js 게임 서버 최종 프로젝트) (0) 2024.08.03 스파르타) The Last Rollback (D-25, Node.js 게임 서버 최종 프로젝트) - timer (0) 2024.08.03 스파르타) The Last Rollback (D-27, Node.js 게임 서버 최종 프로젝트) (0) 2024.07.31 스파르타) The Last Rollback (D-28, Node.js 게임 서버 최종 프로젝트) (0) 2024.07.31 스파르타) The Last Rollback (D-29, Node.js 게임 서버 최종 프로젝트) (0) 2024.07.29