무엇이 잘못된걸까?

기본적인 서버 설정의 문제는 아닐까 싶어 ZEPETO 서버로그를 살펴보니, ZEPETO 월드 ID와 서버 ID가 일치하지 않는 것을 알았고 일치하게 ZEPETO 월드 ID를 수정하였다. 하지만, 그래도 여전히 플레이어 인스턴스가 생성되지 않았다.

image-20220716140620964

먼저, ZEPETO의 플레이어 인스턴스 생성을 이해해야만 했다. 아래 코드는 Zepeto 가이드에서 제공하는 Multiplay - Create Player 코드이다.

OnJoinPlayer(sessionId: string, player: Player) {
 
   // (Editor를 통해 로그인한)UserId를 가져옵니다.
   const userId = WorldService.userId;
   const isLocal = this.room.SessionId === player.sessionId;
 
   // SessionId를 UniqueId로 하여, ZEPETO 캐릭터를 생성합니다.
   ZepetoPlayers.instance.CreatePlayerWithUserId(sessionId, userId, new SpawnInfo(), isLocal);
}

위 코드에서 .CreatePlayerWithUserId() 함수는 서버에서 받아온 sessionId, userId로 플레이어 인스턴스를 생성하는 것 같았다.

내가 작성한 코드를 살펴보니 아래와 같이 ‘ClientStart.ts > OnJoinPlayer()’ 함수에 .CreatePlayerWithUserId() 함수가 포함되어 있었고, 프로그램을 실행 시, console.log가 출력되지 않는 것을 보니 OnJoinPlayer() 함수 호출이 작동하지 않음을 알 수 있었다.

image-20220716141257499

그렇다면, OnJoinPlayer() 함수 호출은 어디서 하는걸까?

아래와 같이 OnStateChange() 함수 영역에서 호출하고 있었고, 빨간색으로 표시한 3개의 영역을 관찰하여 원인을 파악하였다.

image-20220716142312135

먼저, 117번 라인의 변수 join에 문제가 있는 걸까? 그렇다면 먼저, Typescript의 Map 자료구조를 이해해야만 했다.

Map은 <key, value>로 데이터를 저장하는데, key는 중복이 불가능하다.

그렇기 때문에, join한 플레이어의 고유 정보를 담아내기 위해 Map 자료구조를 사용한 것 같다.

다음으로 join한 플레이어 정보를 관리하기 위해 필요한 정보에는 어떠한 것이 있을까?

  • 필요 정보1. sessionId
  • 필요 정보2. Player (zepetoHash, zepetoUserId, transform, state)
// schema에 저장된 room state의 값을 foreach로 하나씩 조회 
state.players.ForEach((sessionId: string, player: Player) => {
	if (this.currentPlayers.has(sessionId)) {
		join.set(sessionId, player);
	}
	// Room에 존재하는 player는 모두 제거하고, 퇴장한 player만 leave에 추가
	leave.delete(sessionId);
});

join.set(sessionId, player); 코드를 보면, 문제 없이 필요 정보가 set이 된것 같지만 여전히 player 인스턴스는 생성되지 않는다.

근본적으로 join한 플레이어를 조회하지 못하기 때문에 발생한 문제로 생각되어 if 문을 살펴보았는데, 역시나…. 조회하는 조건문에 ‘!’가 빠져있었다.

// schema에 저장된 room state의 값을 foreach로 하나씩 조회 
state.players.ForEach((sessionId: string, player: Player) => {
	// currentPlayers 중 sessionId를 가지고 있지 않다면 지금 입장한 player로 봄 
	if (!this.currentPlayers.has(sessionId)) {
		join.set(sessionId, player);
            }
	// Room에 존재하는 player는 모두 제거하고, 퇴장한 player만 leave에 추가
	leave.delete(sessionId);
});

결정적으로 내가 헷갈렸던 이유는

sessionId를 갖고 있는 클라이언트만 플레이어 캐릭터를 생성할 수 있다고 생각하여, ‘!’ 를 빼고 작성했던 것 같다.

하지만, 이 생각은 잘못되었다.

이유는 클라이언트가 Room에 진입했을 때, sessionId가 있는 유저들은 이미 플레이어 캐릭터가 있는 상태고, 입장했음에도 sessionId가 없는 클라이언트는 아직 플레이어 캐릭터가 생성되지 않은 유저로 볼 수 있기 때문에 sessionId가 없는 클라이언트를 join으로 전달하여 플레이어 캐릭터를 생성하는 것이 맞는 논리였다.

아래는 문제를 해결하고 실행시 등장한 나의 멋진 캐릭터이다.

image-20220716145438572

댓글남기기