Technology/Computer
Unity에서 SO와 JSON의 동시 활용 (퀘스트 만들때)
re-moon
2024. 12. 23. 12:44
ScriptableObject(SO)와 JSON을 조합해서 퀘스트 데이터를 관리하면, SO의 편리한 관리 기능과 JSON의 동적 업데이트를 동시에 활용할 수 있습니다. 예를 들어, 퀘스트 데이터를 외부 JSON 파일로 저장해 두고, 이 데이터를 SO로 불러와 사용하는 방법을 구현할 수 있습니다.
1. JSON과 ScriptableObject 조합: 기본 개념
- ScriptableObject: 게임이 실행되는 동안 퀘스트 데이터를 메모리에서 관리.
- JSON: 퀘스트 데이터를 저장하고 필요할 때 업데이트하거나 로드.
- 병합 방식: JSON 데이터를 SO에 반영하거나 SO 데이터를 JSON 파일로 저장.
2. JSON 파일 구조
JSON 파일을 다음과 같이 설계합니다. 퀘스트 데이터를 리스트 형태로 관리합니다.
[
{
"questId": "quest_001",
"title": "Collect Apples",
"description": "Gather 5 apples from the forest.",
"isCompleted": false,
"tasks": [
{
"description": "Collect 5 apples.",
"isCompleted": false
}
]
},
{
"questId": "quest_002",
"title": "Talk to Elder",
"description": "Speak with the village elder about the forest.",
"isCompleted": false,
"tasks": [
{
"description": "Talk to Elder Mark.",
"isCompleted": false
}
]
}
]
3. JSON 데이터를 ScriptableObject로 병합하기
ScriptableObject 클래스 수정
SO에서 JSON 데이터와 매핑될 필드를 정의합니다.
using UnityEngine;
using System.Collections.Generic;
[CreateAssetMenu(fileName = "NewQuest", menuName = "Quest System/Quest")]
public class QuestSO : ScriptableObject
{
public string questId;
public string title;
[TextArea] public string description;
public bool isCompleted;
public List<QuestTask> tasks;
}
[System.Serializable]
public class QuestTask
{
public string description;
public bool isCompleted;
}
JSON 파일을 ScriptableObject로 로드하는 스크립트
JSON 데이터를 ScriptableObject에 적용하려면 아래처럼 **JsonUtility.FromJson**를 사용합니다.
using UnityEngine;
using System.Collections.Generic;
using System.IO;
public class QuestLoader : MonoBehaviour
{
public List<QuestSO> questTemplates; // ScriptableObjects 템플릿 리스트
private string jsonFilePath;
void Start()
{
jsonFilePath = Path.Combine(Application.persistentDataPath, "quests.json");
LoadQuestsFromJson();
}
void LoadQuestsFromJson()
{
if (File.Exists(jsonFilePath))
{
string jsonData = File.ReadAllText(jsonFilePath);
List<QuestData> questList = JsonUtility.FromJson<QuestDataList>(jsonData).quests;
// JSON 데이터를 ScriptableObject로 병합
for (int i = 0; i < questList.Count; i++)
{
if (i < questTemplates.Count)
{
UpdateSOFromJson(questTemplates[i], questList[i]);
}
}
Debug.Log("Quests loaded into ScriptableObjects!");
}
else
{
Debug.LogError("JSON file not found at: " + jsonFilePath);
}
}
void UpdateSOFromJson(QuestSO questSO, QuestData jsonData)
{
questSO.questId = jsonData.questId;
questSO.title = jsonData.title;
questSO.description = jsonData.description;
questSO.isCompleted = jsonData.isCompleted;
questSO.tasks = new List<QuestTask>();
foreach (var task in jsonData.tasks)
{
QuestTask newTask = new QuestTask
{
description = task.description,
isCompleted = task.isCompleted
};
questSO.tasks.Add(newTask);
}
}
}
[System.Serializable]
public class QuestData
{
public string questId;
public string title;
public string description;
public bool isCompleted;
public List<TaskData> tasks;
}
[System.Serializable]
public class TaskData
{
public string description;
public bool isCompleted;
}
[System.Serializable]
public class QuestDataList
{
public List<QuestData> quests;
}
4. ScriptableObject 데이터를 JSON으로 저장하기
SO 데이터를 JSON 파일로 내보낼 수도 있습니다. 이렇게 하면, 런타임 중에 퀘스트 상태를 저장할 수 있습니다.
JSON으로 저장하는 스크립트
using System.IO;
using UnityEngine;
public class QuestSaver : MonoBehaviour
{
public List<QuestSO> questTemplates; // ScriptableObjects 리스트
private string jsonFilePath;
void Start()
{
jsonFilePath = Path.Combine(Application.persistentDataPath, "quests.json");
}
public void SaveQuestsToJson()
{
List<QuestData> questList = new List<QuestData>();
// ScriptableObject를 JSON 데이터로 변환
foreach (QuestSO questSO in questTemplates)
{
QuestData jsonData = new QuestData
{
questId = questSO.questId,
title = questSO.title,
description = questSO.description,
isCompleted = questSO.isCompleted,
tasks = new List<TaskData>()
};
foreach (QuestTask task in questSO.tasks)
{
TaskData taskData = new TaskData
{
description = task.description,
isCompleted = task.isCompleted
};
jsonData.tasks.Add(taskData);
}
questList.Add(jsonData);
}
// JSON으로 저장
QuestDataList dataList = new QuestDataList { quests = questList };
string jsonDataString = JsonUtility.ToJson(dataList, true);
File.WriteAllText(jsonFilePath, jsonDataString);
Debug.Log("Quests saved to JSON file at: " + jsonFilePath);
}
}
5. JSON과 ScriptableObject 병합 활용 예시
퀘스트 데이터 관리 흐름
- 퀘스트 디자이너: Unity에서 ScriptableObject 템플릿을 작성해 기본 데이터를 생성.
- JSON 파일: 런타임에서 데이터 상태를 저장하거나 동적으로 업데이트.
- 병합:
- 로드: JSON 파일의 데이터를 ScriptableObject에 덮어쓰기.
- 저장: ScriptableObject의 데이터를 JSON 파일에 내보내기.
6. JSON과 SO 병합의 장점
- 유연한 업데이트:
- JSON 파일만 수정하면 런타임 중 퀘스트 데이터를 변경 가능.
- 설계 분리:
- 게임 디자이너는 ScriptableObject로 데이터를 직관적으로 관리.
- 개발자는 JSON 파일을 통해 런타임 동작과 저장/불러오기를 구현.
- 대규모 데이터 관리:
- 퀘스트가 수백 개일 때도 JSON 파일을 활용하면 효율적 관리 가능.
결론
ScriptableObject는 퀘스트 데이터를 관리하기에 적합하고, JSON과 결합하면 런타임 동적 업데이트와 저장이 가능합니다. 위 예제를 바탕으로 구현하면 대규모 퀘스트 시스템도 효과적으로 관리할 수 있습니다! 😊