기본적인 저장
대화와 퀘스트를 완성했으니 이제 저장을 해보자.
빈 오브젝트를 생성하고, Save라고 이름을 지었다.
스크립트를 생성하고, 이름은 SaveQuestData라고 했다.
그리고 데이터를 담아둘 Class와 string변수를 만든다.
[System.Serializable]
public class QuestDatas{
public string save;
}
그리고 아래와 같이 스크립팅 한다.
using System.Collections;
using System.Collections.Generic;
using System.IO;
using PixelCrushers.DialogueSystem;
using UnityEngine;
[System.Serializable]
public class QuestDatas{
public string save;
}
public class SaveQuestData : MonoBehaviour
{
public QuestDatas questDatas = new QuestDatas(); //데이터를 담을 클래스
private string path; //데이터가 저장될 경로
private string fileName = "/saveQuestData.txt"; //파일 이름
// Start is called before the first frame update
void Start()
{
path = Application.persistentDataPath + fileName;
}
public void SaveData(){
//Dialog 정보가 있는 PersistentDataManager에서 GetSaveData함수 호출
//Dialog의 정보를 string 형식으로 변환하는 역할
questDatas.save = PersistentDataManager.GetSaveData();
//json형태로 저장
string data = JsonUtility.ToJson(questDatas);
File.WriteAllText(path, data);
}
private void LoadData(){
if(!File.Exists(path)){ //파일이 없다면 새로 저장
SaveData();
}
//파일 읽기
string data = File.ReadAllText(path);
//Json을 파싱
questDatas = JsonUtility.FromJson<QuestDatas>(data);
//Dialog의 변수들을 다시 할당하는 역할을 하는 함수 호출
PersistentDataManager.ApplySaveData(questDatas.save);
}
}
저장을 하고 다시 유니티로 가서 아까 만든 오브젝트에 스크립트를 넣어준다.
대화에서도 저장이 가능하도록 설정
대화중에도 저장이 가능하도록 설정해주자.
Lua형태가 아니기 때문에 작성한 함수 자체로는 대화에서 호출 할 수 없다.
그렇기 때문에 Dialog에서는 커스텀 할 수 있게 제공해주는 것이 있다.
프로젝트폴더에서 Create -> Pixel Crushers -> Dialogue System -> Custom Lua Function Info 를 생성해주자.
생성한 파일에서 SaveData함수를 호출하도록 설정할것이다.
Script Functions에 +버튼을 눌러 요소를 추가해주고, Function Name에 Save라고 입력한다.
스크립트로 돌아와
private void OnEnable() {
Lua.RegisterFunction("Save", this, SymbolExtensions.GetMethodInfo(() => SaveData()));
}
private void OnDisable() {
Lua.UnregisterFunction("Save");
}
위의 함수를 추가해주자.
Dialog 편집기로돌아와서 퀘스트를 받거나 값이 변경되는 지점을 선택한다.
이 노드를 클릭하고,
Script부분에 위와 같이 추가하고 Apply를 해준다.
다른곳도 동일하게 추가한다. (Dialog뿐만 아니라 이전에 만들었던, 아이템이나 오브젝트에도 전부 추가해준다.)
이런식으로 추가해준다.
스크립트로 돌아가 Start함수에 LoadData함수를 작성한다.
그래서 최종적으로 스크립트는 다음과 같다.
using System.Collections;
using System.Collections.Generic;
using System.IO;
using PixelCrushers.DialogueSystem;
using UnityEngine;
[System.Serializable]
public class QuestDatas{
public string save;
}
public class SaveQuestData : MonoBehaviour
{
public QuestDatas questDatas = new QuestDatas(); //데이터를 담을 클래스
private string path; //데이터가 저장될 경로
private string fileName = "/saveQuestData.txt"; //파일 이름
// Start is called before the first frame update
void Start()
{
path = Application.persistentDataPath + fileName;
LoadData();
}
private void OnEnable() {
Lua.RegisterFunction("Save", this, SymbolExtensions.GetMethodInfo(() => SaveData()));
}
private void OnDisable() {
Lua.UnregisterFunction("Save");
}
public void SaveData(){
//Dialog 정보가 있는 PersistentDataManager에서 GetSaveData함수 호출
//Dialog의 정보를 string 형식으로 변환하는 역할
questDatas.save = PersistentDataManager.GetSaveData();
//json형태로 저장
string data = JsonUtility.ToJson(questDatas);
File.WriteAllText(path, data);
}
private void LoadData(){
if(!File.Exists(path)){ //파일이 없다면 새로 저장
SaveData();
}
//파일 읽기
string data = File.ReadAllText(path);
//Json을 파싱
questDatas = JsonUtility.FromJson<QuestDatas>(data);
//Dialog의 변수들을 다시 할당하는 역할을 하는 함수 호출
PersistentDataManager.ApplySaveData(questDatas.save);
}
}
추가작업
퀘스트/ 대화 데이터를 불러왔을 때, 비활성화 되어있던 오브젝트가 활성화 되면 안되기 때문에 이 부분을 수정해야한다.
(이전에 만들었던 Item오브젝트는 상호작용 뒤 비활성화 되도록 처리했었다.)
스크립트를 생성하고, 이름을 OffObject라고 하자.
그리고 생성한 스크립트를 비활성화 되는 오브젝트에 추가하자.
그리고 아래와 같이 스크립트를 작성하자.
using System.Collections;
using System.Collections.Generic;
using PixelCrushers.DialogueSystem;
using UnityEngine;
/// <summary>
/// 원래는 이 내용은 시작되어지는 함수에 작성하면 됨.
/// 지금은 하나의 씬에서 하기 때문에 데이터를 적용하고 불러오는데 약간의 딜레이가 있다.
/// 만약 시작하는 씬이 따로 존재한다면 거기다가 붙여두면 된다.
/// 오프닝씬, 로딩씬에서 데이터를 불러올 때 같이 불러오면 된다.
/// </summary>
public class OffObject : MonoBehaviour
{
string check; //문자를 받는 변수
int count; //카운트되는 변수
private void Update() { //콘솔에서 확인할 수 있도록 Update함수에서 작성
//처음엔 check의 값이 null이기 때문에 success를 반환함.
//퀘스트가 성공이거나, count 가 1보다 크거나 같을 때
if(check == "success" || count >= 1)
return;
//첫번째 인자 : 퀘스트 이름, 두번째 인자 : "State" (퀘스트의 상태)
//퀘스트의 진행여부를 문자열로 받게됨.
check = DialogueLua.GetQuestField("테스트 퀘스트","State").AsString;
//이전에 생성했던 변수의 이름으로 넣어줘야함.
//이렇게 하면 count에 Dialog에서 생성했던 count변수의 값이 들어가게됨.
count = DialogueLua.GetVariable("count").asInt;
Debug.Log($"Check : {check}, count : {count}");
if(check == "success" || count >= 1){ //받아온 뒤엔 success를 반환한다면 이미 끝난 퀘스트
gameObject.SetActive(false);
}
}
}
확인하기
이제 실행해서 퀘스트를 반 정도 진행하고, 두번째 아이템 줍기 퀘스트를 수락한 후 다시 실행해보자.
여기까지 실행한 후, 다시 플레이를 눌러보면
마지막에 진행하던 퀘스트부터 진행할 수 있도록 설정되어있다.
그리고 퀘스트를 완료한 후, 껏다가 다시 켜서 퀘스트창을 살펴보자.
퀘스트 목록에서 완료된 퀘스트 목록이 정상적으로 저장되어있는걸 볼 수 있다.
퀘스트의 저장 경로는 (Windows기준)
C:/ -> user -> user -> AppData -> LocalLow -> DefaultCompany -> project name에 저장된 text파일이다.
퀘스트 목록을 초기화 해주고 싶다면 이 파일을 제거해주면 된다.
다음에 EasySave3을 사용해서 모든 데이터를 저장, 관리 할건데, 어차피 퀘스트 데이터도 Json형식으로 저장된다고 하니 이 둘 을 적절히 섞어서 모두 저장이 되도록 설정하면 좋을것 같긴 하다.
추가로, UI버튼으로 상호작용이 되게 만들 수 있다.
이 부분은 아래 영상에서 30:12 부터 확인해보자.
'Develop > Dialog System' 카테고리의 다른 글
[Dialog System] 유저와 NPC간의 대화를 간편하게 만들어보자! - 2.오브젝트와의 상호작용 (0) | 2024.10.31 |
---|---|
[Dialog System] 유저와 NPC간의 대화를 간편하게 만들어보자! - 1.퀘스트를 생성해보자 (0) | 2024.10.31 |
[Dialog System] 유저와 NPC간의 대화를 간편하게 만들어보자! - 0. 설치와 간단한 대화 만들기 (0) | 2024.10.30 |