wan의 개발일기

RoomCraft #7. 프로젝트 저장/불러오기 — JSON 직렬화 본문

1인 게임개발 활동/가구배치 시뮬레이터

RoomCraft #7. 프로젝트 저장/불러오기 — JSON 직렬화

wan_ 2026. 6. 28. 14:13
소스코드 → github.com/Jywan/RoomCraft

들어가며

지금까지 만든 기능들 — 방 만들고, 가구 배치하고, 회전하고 — 이걸 Play 멈추면 다 날아간다. 매번 처음부터 배치하는 건 말이 안 되니까, 이번에는 JSON으로 저장하고 불러오는 기능을 만든다.


저장 구조 설계

저장해야 할 정보:

  • 방 크기 (가로, 세로, 높이)
  • 배치된 가구들 (치수, 카테고리, 색상, 위치, 회전)

이걸 하나의 ProjectData 클래스로 묶었다.

public class ProjectData
{
    public string projectName;
    public string createdDate;
    public RoomData roomData;
    public List<FurnitureSaveData> furnitureList;
}

Color 직렬화 문제

Unity의 ColorJsonUtility로 직렬화가 안 된다. 그래서 float 4개(R, G, B, A)로 분리 저장했다.

// Color를 float으로 분리 저장
public float colorR;
public float colorG;
public float colorB;
public float colorA;
JsonUtility는 Unity 내장 직렬화 도구인데, Vector3는 되면서 Color는 안 된다. 일관성이 좀 없긴 하다.

FurnitureSaveData — 가구 저장 변환

씬에 있는 FurnitureObject에서 저장용 데이터를 뽑는 메서드와, 반대로 저장 데이터를 FurnitureData로 복원하는 메서드를 만들었다.

// 씬 오브젝트 → 저장 데이터
public static FurnitureSaveData FromFurnitureObject(FurnitureObject obj)
{
    var data = obj.GetData();
    var save = new FurnitureSaveData();

    save.id = data.id;
    save.furnitureName = data.furnitureName;
    save.categoryIndex = (int)data.category;
    save.widthCm = data.widthCm;
    save.depthCm = data.depthCm;
    save.heightCm = data.heightCm;

    save.colorR = data.color.r;
    save.colorG = data.color.g;
    save.colorB = data.color.b;
    save.colorA = data.color.a;

    save.posX = obj.transform.position.x;
    save.posZ = obj.transform.position.z;
    save.rotationY = obj.transform.eulerAngles.y;

    return save;
}

// 저장 데이터 → FurnitureData 복원
public FurnitureData ToFurnitureData()
{
    FurnitureData data = new FurnitureData(
        furnitureName,
        (FurnitureCategory)categoryIndex,
        widthCm, depthCm, heightCm
    );
    data.id = id;
    data.color = new Color(colorR, colorG, colorB, colorA);
    return data;
}

ProjectManager — 파일 입출력

저장 경로

Application.persistentDataPath 아래에 Projects/ 폴더를 만들어서 JSON을 저장한다. 이 경로는 플랫폼마다 자동으로 적절한 위치를 잡아준다.

저장

public void SaveProject(string projectName, RoomData roomData)
{
    ProjectData project = new ProjectData();
    project.projectName = projectName;
    project.roomData = roomData;

    // 씬에 있는 모든 가구를 수집
    FurnitureObject[] allFurniture = FindObjectsByType<FurnitureObject>(FindObjectsSortMode.None);

    foreach (FurnitureObject obj in allFurniture)
    {
        project.furnitureList.Add(FurnitureSaveData.FromFurnitureObject(obj));
    }

    string json = JsonUtility.ToJson(project, true);
    File.WriteAllText(filePath, json);
}

불러오기

public ProjectData LoadProject(string fileName)
{
    string json = File.ReadAllText(filePath);
    ProjectData project = JsonUtility.FromJson<ProjectData>(json);
    return project;
}
JsonUtility.ToJson(project, true)에서 두 번째 인자 true는 pretty print. 사람이 읽을 수 있게 들여쓰기 된 JSON을 생성한다. 디버깅할 때 편하다.

불러오기 시 복원 흐름

  1. 기존 가구 전부 삭제 (Destroy)
  2. 저장된 가구 목록 순회
  3. 각 가구를 CreateFurniture()로 생성
  4. MoveTo()로 저장된 위치로 이동
  5. transform.rotation으로 회전 복원
// 기존 가구 전부 삭제
FurnitureObject[] existing = FindObjectsByType<FurnitureObject>(FindObjectsSortMode.None);
foreach (FurnitureObject obj in existing)
    Destroy(obj.gameObject);

// 저장된 가구 복원
foreach (FurnitureSaveData save in project.furnitureList)
{
    FurnitureData data = save.ToFurnitureData();
    FurnitureObject furniture = interaction.CreateFurniture(data);
    furniture.MoveTo(new Vector3(save.posX, 0f, save.posZ));
    furniture.transform.rotation = Quaternion.Euler(0f, save.rotationY, 0f);
}

정리

기능핵심 구현
프로젝트 데이터ProjectData — 방 + 가구 목록 통합
가구 직렬화FurnitureSaveData — 위치/회전/색상 float 분리 저장
저장JsonUtility.ToJson()File.WriteAllText()
불러오기File.ReadAllText()JsonUtility.FromJson()
저장 경로Application.persistentDataPath/Projects/

현재는 S/L 키로 테스트 중이다. 추후 저장 파일 목록 UI를 만들어서 선택해서 불러오는 기능을 추가할 예정.