일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- kraftonjungle
- 네트워크
- 알고리즘
- 크래프톤 정글
- Unity
- C
- 크래프톤정글
- c#
- 이벤트 함수 실행 순서
- 전쟁-전투
- 핀토스
- 파이썬
- 추상클래스와인터페이스
- 크래프톤 정글 4기
- BFS
- project3
- 4기
- 백준
- User Stack
- KRAFTON JUNGLE
- pintos
- 알고리즘수업-너비우선탐색2
- 티스토리챌린지
- anonymous page
- 유니티
- TiL
- 크래프톤정글4기
- 오블완
- 연결리스트
- 다익스트라
- Today
- Total
말감로그
[Unity] Valley - 인벤토리 저장/로드 (새로하기 &이어하기) 본문
타이틀 씬에서 새로하기, 이어하기 버튼을 클릭 했을 때 각 저장된 인벤토리 데이터에 맞게 로드하고 인 게임씬으로 전환되도록 할 것이다.
우선 새로하기 버튼은 말 그대로 저장된 인벤토리 데이터가 없거나, 있는데 새로하려고 할 때 인벤토리 데이터를 지우고, 인벤토리를 초기화한다.
이어하기 버튼은 저장된 데이터가 있을 때, 그 데이터를 불러와 게임을 이어서 플레이할수 있도록 한다.
HasSavedInventory() 함수를 통해 해당 경로에 각 인벤토리 텍스트 파일이 존재하는지 확인해서 저장된 인벤토리 여부를 리턴한다.
//InventorySave.cs
public bool HasSavedInventory()
{
string backpackPath = Application.persistentDataPath + "/Backpack.txt";
string toolbarPath = Application.persistentDataPath + "/Toolbar.txt";
return File.Exists(backpackPath) || File.Exists(toolbarPath);
}
그리고 저장된 인벤토리 파일을 지우고 인벤토리 슬롯을 초기화하는 함수도 생성했다.
//InventorySave.cs
public void DeleteSavedFiles()
{
string[] filePaths = Directory.GetFiles(Application.persistentDataPath, "*.txt");
foreach (string filePath in filePaths)
{
File.Delete(filePath);
}
Debug.Log("All inventory files deleted at game start.");
}
InventoryManager.cs 에 inventoryByName 딕셔너리에 있는 인벤토리들을 찾아 해당 슬롯을 Clear하게 했다.
//InventoryManger.cs
public void ClearInventory()
{
foreach (var inventory in inventoryByName.Values)
{
inventory.Clear();
}
}
이제 타이틀 씬에서 각 버튼을 클릭했을 때 저장된 인벤토리 파일의 여부에 따라 isNewGame의 값을 변경해주고
인게임 씬으로 전환되도록 했다.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class TitleUIManager : MonoBehaviour
{
:
:
void Start()
{
GameObject inventoryObj = new GameObject("InventorySave");
InventorySave inventorySave = inventoryObj.AddComponent<InventorySave>();
if (!inventorySave.HasSavedInventory())
{
isNewGame = true;
continueGameBtn.gameObject.SetActive(false);
newGameBtn.onClick.AddListener(() =>
{
SceneManager.LoadScene("InGameScene");
});
}
else
{
isNewGame = false;
continueGameBtn.gameObject.SetActive(true);
continueGameBtn.onClick.AddListener(() =>
{
SceneManager.LoadScene("InGameScene");
});
}
exitGameBtn.onClick.AddListener(()=>
{
Application.Quit();
});
}
}
그리고 InGameScene으로 전환될 때 GameManager.cs에서 isNewGame의 값에 따라서 저장된 데이터를 로드할 지, 아니면 새로 초기화를 할 지를 정해주었다.
SceneManager.sceneLoad += OnSceneLoaded;
OnSceneLoaded 메서드를 씬이 로드될 때 호출되는 이벤트에 등록하여, 씬이 로드될 때마다 자동으로 메서드가 실행되게 한다.
public class GameManager : MonoBehaviour
{
:
void Awake()
{
:
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (scene.name == "InGameScene")
{
if (TitleUIManager.instance.isNewGame)
{
player.inventoryManager.ClearInventory();
inventorySave.DeleteSavedFiles();
}
else
{
player.inventoryManager.LoadInventory();
}
}
}
void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
}
이미 저장된 데이터가 있는데 새로하기 버튼을 클릭 했을 때의 팝업을 생성하고, 아니요를 누르면 팝업이 꺼지고, 네를 누르면 저장된 데이터를 지워버리는 기능을 추가했다.
그러나 팝업이 떴을 때 아니요 버튼을 클릭하고 네 버튼을 클릭하면 MissingReferenceException 에러가 엄청 뜨면서 참조된 객체가 삭제되는 현상이 발생했다.
확인해보니 버튼 리스너 증복 등록 때문이라고 한다. (gpt가)
원인 분석
- 버튼 리스너 중복 등록:
- "네" 버튼을 클릭했을 때, 이미 리스너가 등록된 버튼에 대해 다시 리스너를 추가하려고 하면, 이전 리스너들이 계속 남아 있을 수 있습니다. 이 경우에도 MissingReferenceException이 발생할 수 있습니다.
해결 방법
1. 버튼에 리스너 중복 등록 방지
yesBtn과 noBtn에 클릭 리스너를 여러 번 추가하는 문제가 있을 수 있습니다. 예를 들어, "네" 버튼을 클릭할 때마다 리스너가 계속 추가되면, 버튼을 다시 클릭할 때마다 여러 번 실행되거나, 잘못된 객체에 접근하게 될 수 있습니다.
이를 방지하기 위해, 버튼에 리스너를 추가하기 전에 기존의 리스너를 제거하는 것이 필요합니다.
newGameBtn.onClick.AddListener(() =>
{
// 기존 리스너 제거 (중복 등록 방지)
yesBtn.onClick.RemoveAllListeners();
noBtn.onClick.RemoveAllListeners();
panel.SetActive(true);
yesBtn.onClick.AddListener(() => { isNewGame = true; SceneManager.LoadScene("InGameScene"); });
noBtn.onClick.AddListener(() => { panel.SetActive(false); });
});
그래서 중복 등록 방지를 위해 RemoveAllListeners() 함수를 통해 기존 리스너를 제거해주니 에러가 발생하지 않았다.
저장된 인벤토리 데이터 파일이 있기 때문에 이어하기 버튼이 활성화되었고, 이어하기 버튼을 누르면 각 데이터를 토대로 로드되는 걸 볼 수 있다.
데이터가 있는 상태에서 새로하기 버튼을 누를 때
네 버튼을 누르면 파일도 사라지고, 인벤토리도 초기화 된 것을 볼 수 있다.
'TIL' 카테고리의 다른 글
[Unity] Valley - 식물 로드 버그 수정 (0) | 2024.11.14 |
---|---|
[Unity] Valley - 식물 데이터 저장/로드 (새로하기 & 이어하기) (0) | 2024.11.13 |
[Unity] Valley - 인벤토리 저장 & 로드 시스템 (2) | 2024.11.12 |
[Unity] Valley - 판매 가능한 아이템 설정 (0) | 2024.10.30 |
[Unity] Valley - 아이템 팔기(+ 아이템 판넬 UI) (2) | 2024.10.29 |