wan의 개발일기
RoomCraft #10. 씬 분리 — 시작 화면 만들기 본문
소스코드 → github.com/Jywan/RoomCraft
들어가며
지난 편에서 저장/불러오기 UI를 팝업으로 만들려고 시도했었다. 근데 패널이 겹치고, Inspector 연결이 꼬이고, NullReferenceException이 터지고… 문제가 끝도 없이 나왔다.
결국 한 씬 안에 모든 걸 욱여넣는 건 무리라는 결론에 도달했다. 그래서 이번에는 씬을 아예 분리하기로 했다. 시작 화면에서 프로젝트를 선택하고, 에디터 씬으로 넘어가는 구조다.
왜 씬을 분리했나
모든 UI가 한 씬에 있으면 이런 문제들이 생긴다:
- 패널 겹침/순서 문제 — Canvas 안에서 UI 요소끼리 가려지거나 클릭이 안 먹는 상황
- NullReferenceException — Start() 시점에 아직 비활성화된 오브젝트를 참조하려다 터짐
- 관리 복잡성 — 하나의 씬에 너무 많은 책임이 몰림
그래서 StartScene(시작 메뉴)과 EditorScene(가구 배치 에디터), 두 씬으로 나눴다. 역할이 명확해지니까 각 씬의 UI 로직이 단순해졌다.
SessionData — 씬 간 데이터 전달
씬이 분리되면 가장 먼저 부딪히는 문제가 “데이터를 어떻게 넘기지?”다. Unity에서 SceneManager.LoadScene()을 호출하면 이전 씬의 오브젝트가 전부 파괴되니까, MonoBehaviour에 데이터를 담아두는 건 안 된다.
해결법은 간단하다. static 클래스를 하나 만들어서 StartScene에서 설정한 정보를 EditorScene에서 읽어가게 했다.
namespace RoomCraft.Data
{
/// <summary>
/// 씬간 데이터 전달용 static 클래스
/// StartScene에서 설정 -> EditorScene에서 읽어감
/// </summary>
public static class SessionData
{
public enum Mode { NewProject, LoadProject }
public static Mode CurrentMode { get; set; }
// 새 프로젝트일 때 사용
public static string RoomName { get; set; }
public static float RoomWidth { get; set; }
public static float RoomDepth { get; set; }
public static float RoomHeight { get; set; }
// 불러오기일 때 사용
public static string LoadFileName { get; set; }
public static void SetNewProject(string name, float width, float depth, float height)
{
CurrentMode = Mode.NewProject;
RoomName = name;
RoomWidth = width;
RoomDepth = depth;
RoomHeight = height;
LoadFileName = null;
}
public static void SetLoadProject(string fileName)
{
CurrentMode = Mode.LoadProject;
LoadFileName = fileName;
RoomName = null;
}
}
}
핵심은 SetNewProject()와 SetLoadProject() 두 메서드다. StartScene에서 이 중 하나를 호출하고, EditorScene에서 CurrentMode를 확인해서 분기하면 된다.
StartSceneUI — 시작 화면
StartScene은 단순한 구조다. 타이틀이 있고, 아래에 버튼 두 개 — “새 프로젝트”와 “불러오기”.
EditorSceneLoader — 에디터 진입
EditorScene에 진입하면 EditorSceneLoader가 SessionData를 읽어서 분기한다.
SessionData.CurrentMode가 NewProject면 방을 새로 생성하고, LoadProject면 저장된 프로젝트를 복원한다.
private void HandleNewProject()
{
RoomData roomData = new RoomData(
SessionData.RoomWidth,
SessionData.RoomDepth,
SessionData.RoomHeight,
SessionData.RoomName);
roomBuilder.BuildRoom(roomData);
CameraController cam = FindAnyObjectByType<CameraController>();
if (cam != null)
{
cam.SetTargetPoint(Vector3.zero);
cam.SwitchMode(CameraMode.TopView);
}
}
StartScene에서 입력한 방 크기로 RoomData를 만들고, BuildRoom()으로 방을 생성한다. 그 다음 카메라를 탑뷰로 전환해서 바로 배치 화면을 보여준다.
삽질 기록
SavePanel이 시작부터 열려있다
Start()에서 패널을 SetActive(false)로 꺼야 하는데, 그 전에 NullReferenceException이 터져서 패널이 안 꺼지는 문제가 있었다. 원인은 Inspector에서 필드 연결을 빠뜨린 것. SerializeField로 선언한 변수에 오브젝트를 드래그해서 연결하지 않으면, Start() 첫 줄에서 바로 터진다.
해결: Inspector에서 필드 연결 확인. 빈 칸 없이 전부 채워야 한다.
버튼 클릭이 안 된다
Start()가 비어있거나, 메서드 이름에 오타가 있어서(OpenNNewProjectPanel처럼 N이 두 번) 리스너가 등록되지 않았던 문제.
해결: 오타 수정하고 Start() 내용을 제대로 작성.
방이 400m로 만들어진다
InputField에 Placeholder를 “400”으로 해놓고, 단위를 cm로 생각했는데 RoomData는 m 단위였다. 그러니까 가로 400m짜리 방이 만들어진 거다.
해결: Placeholder를 m 단위로 바꾸고(4, 3, 2.5), 기본값도 4f, 3f, 2.5f로 설정.
정리
| 기능 | 핵심 구현 |
|---|---|
| 씬 분리 | StartScene(index 0) + EditorScene(index 1), SceneManager.LoadScene() |
| 데이터 전달 | SessionData static 클래스, SetNewProject() / SetLoadProject() |
| 시작 화면 | StartSceneUI — 새 프로젝트 패널 + 불러오기 패널 |
| 에디터 진입 | EditorSceneLoader.HandleNewProject() — RoomBuilder.BuildRoom() |
| 카메라 초기화 | CameraController.SetTargetPoint() + SwitchMode(TopView) |
다음 편에서는 EditorScene에 저장 기능을 붙이고, 불러오기 흐름을 완성해보려고 한다.
'1인 게임개발 활동 > 가구배치 시뮬레이터' 카테고리의 다른 글
| RoomCraft #12. 룸/가구 툴바 분리 + 색상 피커 만들기 (0) | 2026.07.05 |
|---|---|
| RoomCraft #11. 에디터 툴바 — 키보드에서 버튼으로 (0) | 2026.07.02 |
| RoomCraft #9. 방 커스터마이징 — 사용자 입력으로 방 크기 설정 (0) | 2026.06.28 |
| RoomCraft #8. 그리드 스냅 + 치수 표시 — 정렬 도우미와 가구 정보 UI (0) | 2026.06.28 |
| RoomCraft #7. 프로젝트 저장/불러오기 — JSON 직렬화 (0) | 2026.06.28 |