TIL

[멋사 부트캠프] 오목 게임 만들기 : 간단한 멀티플레이 구현

Cadi 2025. 3. 20. 09:32

목표

1. 게임 방 연결

2. 플레이어 정보 전달

3. 착수 정보 전달




01. 게임 방 연결 성공

 

올바르게 RoomId를 전달하고, 올바르게 받아와 플레이어 정보 전달 성공

 

 

2. 플레이어 정보 전달

 

UserData라는 클래스 형태로 데이터를 받고 있기 때문에 , 서버에서 보낼 때에도

객체로 감싸주어야 GetValue<UserData>(); 가 잘 작동함.

 

 

3. 착수 정보 전달

 

CurrentIndex 문제

현재 착수 부분에서 플레이어 2 ( 두 번째 플레이어 ) 가 착수를 하면 다음과 같은 오류가 발생

IndexOutOfRangeException: Index was outside the bounds of the array.

protected void ProcessMove(GameLogic gameLogic, Constants.PlayerType playerType, int row, int col)
{
    if (gameLogic.SetNewBoardValue(playerType, row, col))
    {
        gameLogic.blockController.SelectMarker(row, col, false);
        if (gameLogic.currentIndex != -2)
        {
            //TODO: 테스트용 코드
           // gameLogic.blockController.CurrentMarkerCheck(playerType,gameLogic.currentIndex/15, gameLogic.currentIndex%15, false);
            gameLogic.blockController.CurrentMarkerCheck(playerType , row, col, false);
        }
        gameLogic.blockController.CurrentMarkerCheck(playerType,row, col, true);
        
        gameLogic.currentIndex=gameLogic.selectIndex;
        
        HandleNextTurn(gameLogic);
        
    }
}

기존 코드에서는 currentIndex/15를 통해 row, col을 지정하는데, 현재 currentIndex가 제대로 변경되지 않는 문제가 있어 일단 주석처리함. 추후 클라이언트쪽에 요청할 예정

(아마 전에 착수했던 지점을 기억하고, 그 지점의 효과 - 마지막 착수 지점 효과 - 를 빼려고 했던 코드인 것 같으나 currentIndex가 제대로 업데이트 되지 않아 문제가 발생한 것이라고 생각 . )

 

 

싱글플레이 / 멀티플레이 문제

public void SetState(BasePlayerState state)
    {
        UnityThread.executeInUpdate(() => { 
            Debug.Log("Set State");
            _currentPlayerState?.OnExit(this);
            _currentPlayerState = state;
            _currentPlayerState?.OnEnter(this);
        });
        
        // _currentPlayerState?.OnExit(this);
        // _currentPlayerState = state;
        // _currentPlayerState?.OnEnter(this);
        
    }

유니티스레드에서 실행하면 싱글플레이가 안되는 문제가 있음

매개변수로 멀티/싱글을 받아 다르게 적용하는 방법이 필요함. 멀티 플레이 구분 문제

 

 

 질문 : 왜 똑같이 업데이트에 실행을 맡기는 구조인데, 싱글 플레이일때는 작동하지 않는가 ? 

 

UnityThread에 작동 원리를 알아야 한다. 

UnityThread는 자신을 호출한 객체의 생애주기 안에서 실행되는 것이라 생애주기가 없는 객체에 붙어있다면

내부적으로 Queue에 저장은 되지만 Update()함수가 소비해 주지 못하기 때문에 실행되지 못한다. 

 

GameLogic Class가 Monobehaviour를 상속받고 있지 않기 때문에, 실행을 대리로 맡겨도 동작하지 못했던 것이다.

반면, 멀티플레이일 때는 왜 실행이 되었을까 ? 

case Constants.GameType.MultiPlayer:
{
    
    _multiplayManager = new MultiplayManager((state, roomId) =>
    {
       ~~~ 생략  ~~~
                
                // 게임 시작
                SetState(firstPlayerState);
                ~~~ 생략  ~~~
    }

 

이런 식으로 _multiPlayManager 안에서 SetState 함수를 호출하기 때문에 , Monobehaviour를 상속받은 _multiPlayManager 객체에 대리 실행을 맡기게 되고, 정상 실행되는 결과가 나오는 것이다. 

 

 

* 추가로 생각해야 될 문제 : 타이머가 게임 중일 때만 돌아가는 문제 // 혹은 타이머 동기화 ? 

* 현재 상대방의 정보를 받아와서 세팅하긴 하지만, 자신의 정보는 세팅하지 않고 있음. 

 

 

 

현재까지의 결과물