본문 바로가기
프로젝트

24/11/05 - [개인] 멀티 플레이 과제: 멀티 플레이어 이동 테스트

by Jini_Lamp 2024. 11. 5.

몸상태 이슈로 강의를 겨우 듣고, 이제서야 과제를 진행하게 되었다.

팀 프로젝트도 있어 조금이라도 빨리 제출을 해야 했기 때문에, 올라온 해답 영상을 보면서 진행하하게 되었다.

해서, 이번에는 필요한 부분만 정리해서 게시물을 올리고자 한다.

 

먼저, 과제의 내용을 설명하자면 지난 프로젝트 내용과 비슷하다.

한가지 다른 점이 있다면 이번에는 유니티로 클라이언트를 열고, 플레이어의 움직임을 직접 확인한다는 점일까.

그렇다보니 전반적으로 코드는 이전과 유사한 부분이 많았다.

 

그러나 2인 이상의 클라이언트가 서버에 접속을 하고자 했을 때, 아래와 같은 상황이 발생했다.

 

TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received type number (0)

 

즉, string 타입이 예상되는 위치에 숫자 타입이 들어갔다는 소리다.

좀 더 분석을 해보자면 데이터를 인코딩 할 때 프로토콜 버퍼 필드 정의와 전달되는 데이터 타입이 맞지 않을 때 발생하는 오류인데, 디버깅으로 위치를 확인해보니 아래 코드에서 문제가 발생했다는 걸 알았다.

export const createLocationPacket = (users) => {
    const protoMessages = getProtoMessages();
    const location = protoMessages.gameNotification.LocationUpdate;

    const payload = { users };
    const message = location.create(payload);
    const locationPacket = location.encode(message).finish();	// <= 문제가 생긴 부분

    return serializer(locationPacket, PACKET_TYPE.LOCATION);
};

 

즉, encode()에 들어가는 message가 잘못되었다는 뜻이다. message는 payload 값을 프로토콜 버퍼 메시지로 변환해주고, payload는 매개변수 users를 값으로 받는다.

그리고 users의 값은 이곳에서 정의된다.

    // 나(userId)를 제외한 다른 유저들의 위치값...
    getAllLocation(userId) {
        const locationData = this.users
            .filter((user) => {
                return user.id !== userId;
            })
            .map((user) => {
                return { id: user.id, playerId: user.playerId, x: user.x, y: user.y };
            });
        return createLocationPacket(locationData);
    }

 

요컨대 해당 코드에서 데이터 타입이 다른 무언가로 createLocationPacket()에 보내주고 있다는 뜻인데, 이를 확인하기 위해 map() 부분에 breakPoint를 찍은 후 디버그로 값을 확인했다.

(이를 확인하기 위해선 먼저 서로 다른 클라이언트가 2개 준비되어야 한다.)

 

여기까지 확인을 했다면 gameNotification.LocationUpdate의 각 필드들의 타입을 확인해야 한다.

syntax = "proto3";

package gameNotification;

message LocationUpdate {
    repeated UserLocation users = 1;

    message UserLocation {
        string id = 1;
        string playerId = 2;
        float x = 3;
        float y = 4;
    }
}

 

보다시피, gameNotification.LocationUpdate의 playerId는 string 타입인데, 코드에서 받고 있는 차입은 Num이다.

즉, 이번 에러는 서버와 클라언트의 playerId 타입이 달라서 생긴 문제였다.

 

그렇다면 어느 쪽이 문제일까?

클라이언트 부분은 내가 작성한 게 아니니, 건들 부분은 없다. 그렇다는 건 서버 쪽에서 타입 정의를 잘못했다는건데... 나는 다시 한번 과제에서 정의해준 프로토버프 정의를 살펴보았다.

......

 

해서, 나는 gameNotification.LocationUpdate를 다음과 같이 변경했다.

syntax = "proto3";

package gameNotification;

message LocationUpdate {
    repeated UserLocation users = 1;

    message UserLocation {
        string id = 1;
        uint32 playerId = 2;
        float x = 3;
        float y = 4;
    }
}

 

그리고 다시 결과를 확인해보면...

정상적으로 동작하는 걸 확인할 수 있다.