게임의 기본 루프를 완성해보자.
리셋할 때 에디터 시뮬레이팅을 재시작하지 않아도 돼서 테스트가 용이해지고,
씬을 왔다 갔다 할 수 있기 때문에 자원 생성과 회수에 대해 미흡했던 부분을 찾아 수정할 수 있다.
서버 통신 전에 만들어 두면 통신 타이밍을 바로 연결시킬 수도 있다.
목표 기본 흐름은 크게 메인씬 - 플레이씬 - 공격/피격 - 승/패 처리 및 게임 종료 - 메인씬 이다.
씬 이동간에 팝업이 있으면 편리하기 때문에 팝업 시스템도 같이 개발하려고 한다.

먼저 씬 이동 시스템을 구축해야한다.
필요한 MonoBehaviour 상속 매니저 오브젝트들을 정리하고 DontDestoryOnLoad 처리해 준다.
이 중요 오브젝트들을 메인씬에 두게되면, 메인씬과 플레이씬을 오갈때마다 재생성되어 의도한 바가 아니게 된다.
따라서 스플래시씬을 만들어서 거기로 옮겨두었다.
게임 시작하자마자 보통 로딩 화면이 나오는데, 이에 해당한다. 기타 에셋 로딩이나 서버 연결들도 진행할 수 있다.
Scene currentScene = SceneManager.GetActiveScene();
// 다음 씬 Load
var op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
...
// 다음 씬 Activate
Scene loadedScene = SceneManager.GetSceneByName(sceneName);
SceneManager.SetActiveScene(loadedScene);
// 기존 씬 Unload
op = SceneManager.UnloadSceneAsync(currentScene);
...
씬은 비동기로 로드해준 뒤 로딩 화면을 보여준다.
씬이 무거워질 수록 1프레임에 로드하고 그리게 되면 프레임드랍이 일어날 수 있기 때문이다.
Additive 옵션을 줘서 기존 씬 위에 다음 씬을 로드하도록 하고,
모두 로드가 된 이후에 기존 씬을 언로드하는 방식으로 해서 자연스럽게 이동할 수 있도록 한다.
각 씬에는 버튼 액션을 담당하는 씬 핸들러를 연결시켜 준다.
메인씬에서는 플레이 버튼을 누르면 그 액션으로 매칭 팝업을 보여주기만 하고,
매칭 팝업에서 매칭이 끝나면 플레이씬으로 이동 시켜주는 구조다.

팝업은 조금 복잡한 기능이라 구체적인 관리 시스템이 들어가면 편리해진다.
예를 들어 씬에서 A팝업을 열고, A팝업에서 B팝업을 열 수 있는 상황에서
그려지는 순서는 씬 위에 A팝업 위에 B팝업이 그려져야 하고,
B팝업은 데이터를 표시하기 위해 A팝업에게 특정 데이터를 넘겨받을 수 있어야 하며,
A팝업은 B팝업에서 어느 버튼을 눌렀는지에 대한 결과를 받아서 다음 행동을 취할 수 있어야 한다.
이를 구현하기 위해 우선 abstract 팝업 핸들러를 만들어 각 팝업에 연결해 준다.
해당 팝업에게 데이터를 주거나 받을 때는 inner abstract class 2개를 두어 상속 및 구현하여 사용할 수 있게 한다.
그리고 이들을 관리해주는 팝업 매니저 클래스를 만들어 아래와 같이 사용하도록 한다.
var param = new TwoButtonPopup.Param("Exit", "Are you sure you want to exit?");
var result = await PopupManager.Instance.ShowAsync(nameof(TwoButtonPopup), param);
if (result is TwoButtonPopup.Result { isClickedOk: true }) {
Application.Quit();
}
일반적인 두개의 버튼을 가지고 있는 팝업에게 타이틀과 설명 글을 파라미터로 전달하여 표시하게 하고,
그 팝업에서 무슨 버튼을 눌렀는지를 바깥에서 반환받아 다음 행동을 할 수 있게 된다.

플레이씬에서도 똑같이 메인씬으로 나갈 수 있어야 하므로, 버튼을 만들어 준다.

이쯤되면 편의성으로 하나의 기능을 만들고 싶어진다.
Esc 키를 눌러 로 맨 위의 팝업을 하나씩 닫는 기능과, 팝업이 아무 것도 안 켜져있을 때 종료 팝업을 띄우는 기능이다.
이는 팝업에서 관여하기보다는 씬 내에서만 존재하면 되는 기능이므로 씬 핸들러에 적용시켜 두면 되겠다.
플레이씬에서도 동일하게 적용시키고 싶으므로 부모 클래스를 하나 만들어 공통 기능을 적용시킨 뒤,
메인씬 핸들러와 플레이씬 핸들러가 이를 상속받게 한다.
기능은 단순히 Update 메서드에서 Esc 인풋을 감지해 현재 열려있는 팝업을 판단해 구현하면 된다.

마지막으로 인게임 내에서의 루프도 만들면 좋을 것 같다.
어찌보면 코어 로직에도 연관이 있는 것인데, 공격에 의한 투사체가 다른 플레이어와 충돌했을 때 피격을 받는 시스템이다.
먼저, 플레이어 위에 hp 바가 있어야 할 것이다.
캐릭터별 최대 체력으로 초기화시켜두고, 피격받았을 때 애니메이션으로 피통이 줄어드는 것을 시각화 한다.
애니메이션은 DOTween을 사용했다. 이건 정말 안 쓰면 손해인 것 같다 ㅎ..
hp바를 SpriteRenderer로 할 지, UI Image로 할 지 고민하다가,
개발과 유지보수가 편한 쪽인 플레이어별 개별 캔버스 + UI Image로 구현했다.

이렇게 내 플레이어만 살게 되면 승리로 판단하고, 내 플레이어가 죽게 되면 패배로 판단하여 종료시킬 수 있다.
코어쪽 시뮬레이터 맨 마지막에 게임 종료를 판단한다.
사망한 플레이어는 시뮬레이터에서 관리하는 플레이어 리스트에서 틱마다 제외시킨다.
관리하는 플레이어의 수에서 사망해서 제외될 플레이어의 수의 차로 게임의 종료를 판단할 수 있다.
모두 한 틱에 사망하여 공동 승리한 경우는 차가 0이다.
이때는 이전 틱에 몇 명이 남았는지 상관 없이 남은 플레이어들을 모두 공동 승리시킨다.
차가 1인 경우 최후의 승리자가 발생한 경우다.
이때는 승리자에게 승리했다고 알려주고, 나머지 패배자들은 사망 로직을 타게 되어 게임이 종료될 수 있게 한다.
이제 조금 루프 기반이 만들어져서 마음이 편해진 느낌이다 ㅋㅋ
다음엔 정말 서버 통신을 UI에 이어볼 수 있을 것 같다.
이참에 조금 부족했던 HTTP 관련 공부를 같이 곁들이면 더 좋을 것 같다는 생각이 들었다.
'Devlog > Crawl-Stars' 카테고리의 다른 글
| [Devlog] 로컬 프로토타이핑 - 브롤스타즈 모작 #1 (0) | 2026.06.01 |
|---|---|
| [Devlog] 또 다른 시작 - 브롤스타즈 모작 #0 (0) | 2026.05.29 |