현재 코기 엔진의 세이브 기능을 활용해서 세이브 창을 만들고 있다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MoreMountains.Tools;
using UnityEngine.SceneManagement;
[System.Serializable]
public struct SerializableVector3
{
public float x, y, z;
public SerializableVector3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public SerializableVector3(Vector3 vector)
{
this.x = vector.x;
this.y = vector.y;
this.z = vector.z;
}
public Vector3 ToVector3()
{
return new Vector3(x, y, z);
}
}
[System.Serializable]
public class PlayerSaveData
{
public SerializableVector3 savePosition; // Vector3 → SerializableVector3 변경
public PlayerSaveData()
{
savePosition = new SerializableVector3(0, 0, 0);
}
public PlayerSaveData(Transform pos)
{
savePosition = new SerializableVector3(pos.position); // Vector3을 변환하여 저장
}
public Vector3 GetPosition()
{
return savePosition.ToVector3(); // 다시 Vector3로 변환
}
}
public class saveManager : MonoBehaviour
{
public Transform playerTransform;
private const string SaveFileName = "PlayerPosition.save";
private const string SaveFolder = "PlayerData";
private static PlayerSaveData loadedData;
private void Awake()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDestroy()
{
// 씬이 변경될 때마다 중복 호출 방지를 위해 이벤트 제거
SceneManager.sceneLoaded -= OnSceneLoaded;
}
// 게임 저장
public void SaveGame()
{
playerTransform = GameObject.FindWithTag("Player").transform;
if (playerTransform == null)
{
Debug.LogError("플레이어 Transform이 연결되지 않았습니다!");
return;
}
PlayerSaveData saveData = new PlayerSaveData(playerTransform);
MMSaveLoadManager.Save(saveData, SaveFileName, SaveFolder);
Debug.Log("게임 저장 완료! 위치: " + saveData.savePosition.x + ", " + saveData.savePosition.y + ", " + saveData.savePosition.z);
}
// 씬을 다시 로드한 후, 저장된 위치로 플레이어 이동
public void LoadGame()
{
object loadedObject = MMSaveLoadManager.Load(typeof(PlayerSaveData), SaveFileName, SaveFolder);
if (loadedObject == null)
{
Debug.LogWarning("저장된 데이터가 없습니다!");
return;
}
loadedData = (PlayerSaveData)loadedObject;
Debug.Log("저장된 데이터 로드 완료. 씬을 다시 로드합니다...");
// 씬 다시 로드
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
StartCoroutine(WaitAndSetPosition());
}
private IEnumerator WaitAndSetPosition()
{
yield return new WaitForSeconds(0.5f);
if (loadedData != null)
{
GameObject player = GameObject.FindWithTag("Player");
if (player != null)
{
player.transform.position = loadedData.GetPosition();
Debug.Log("플레이어 위치 복원 완료! 위치: " + player.transform.position);
}
else
{
Debug.LogError("씬에서 플레이어를 찾을 수 없습니다! 플레이어가 생성되었는지 확인하세요.");
}
loadedData = null;
}
}
public void DeleteSave()
{
MMSaveLoadManager.DeleteSave(SaveFileName, SaveFolder);
Debug.Log("저장된 데이터 삭제 완료!");
}
}
세이브 기능을 관리하는 매니저 이며
using MoreMountains.CorgiEngine;
using UnityEngine;
using UnityEditor;
public class saveArea : MonoBehaviour
{
private bool playerInArea = false; // 플레이어가 영역 안에 있는지 확인
private saveManager saveManager;
private void Awake() {
saveManager = GameObject.Find("saveManager").GetComponent<saveManager>();
}
[MenuItem("Custom Menu/customLoad")]
private static void MyCustomMethod()
{
LoadCustom();
}
private void Update() {
if (playerInArea && Input.GetKeyDown(KeyCode.L))
{
Debug.Log("플레이어 저장");
saveManager.SaveGame();
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
playerInArea = true;
Debug.Log("플레이어가 저장 영역에 들어왔습니다!");
}
}
static private void LoadCustom()
{
saveManager instance = GameObject.FindObjectOfType<saveManager>();
if (instance == null)
{
Debug.LogError("saveManager 인스턴스를 찾을 수 없습니다!");
return;
}
instance.LoadGame();
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
playerInArea = false;
Debug.Log("플레이어가 저장 영역을 벗어났습니다.");
}
}
public bool IsPlayerInSaveArea()
{
return playerInArea;
}
}
세이브 구역을 관리하는 스크립트이다
현재 구조는 플레이어 캐릭터가 세이브 구역에 들어가면 인식 후, 특정키 = 현재는 L키를 누르면 세이브 기능이 사용되며, 로드는 커스텀 메뉴에서 사용되는 경우이다
현재 구조로는
휴식하는 공간 진입 => 세이브 기능 or 정비 기능 버튼이 나오고, 세이브 기능 버튼을 누르면 세이브 버튼이 나오고, 버튼을 누르면 세이브가 되는 형식이다
현재 UI와는 연결되어 있지 않다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RestUIControl : MonoBehaviour
{
[SerializeField]
private saveManager saveManager;
[SerializeField]
private GameObject RestLayerUI;
[SerializeField]
private GameObject SaveLayerUI;
public void GotoSaveLayerBtn()
{
RestLayerUI.SetActive(false);
SaveLayerUI.SetActive(true);
}
public void BacktoRestLayerBtn()
{
RestLayerUI.SetActive(true);
SaveLayerUI.SetActive(false);
}
public void SaveBtnA()
{
saveManager.SaveGame();
}
}
UI를 관리하는 스크립트이며, 여기에 saveManager를 객체로 가져와서 사용한다
public void SaveBtnA()
{
saveManager.SaveGame();
BacktoRestLayerBtn();
gameObject.SetActive(false);
}
이 함수를 실행해서 저장을 하도록 한다
이제 L키를 눌렀을때 RestUI가 나오도록 해야 한다
private void Update() {
if (playerInArea && Input.GetKeyDown(KeyCode.L))
{
Debug.Log("플레이어 저장");
saveManager.SaveGame();
}
}
현재 이런 구조를 가지고 있는데, 이를 조금 수정한다
[SerializeField]
private GameObject RestUI;
RestUI.SetActive(true);
이런 줄을 추가해서 관리한다
나중에 GameObject를 자동으로 할당하도록 수정해야 한다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RestUIControl : MonoBehaviour
{
[SerializeField]
private GameObject RestLayerUI;
[SerializeField]
private GameObject SaveLayerUI;
public void GotoSaveLayerBtn()
{
RestLayerUI.SetActive(false);
SaveLayerUI.SetActive(true);
}
public void BacktoRestLayerBtn()
{
RestLayerUI.SetActive(true);
SaveLayerUI.SetActive(false);
}
public void SaveBtnA()
{
saveManager.Instance.SaveGame();
BacktoRestLayerBtn();
gameObject.SetActive(false);
}
}
'개발일지 > 게임개발' 카테고리의 다른 글
유니티 Talk BackLogBar 개발 (0) | 2025.04.29 |
---|---|
Unity effect maker 제작 (0) | 2025.04.29 |
유니티 3D 게임 개발 - 체력, 총알 수 UI 제작 (1) | 2024.12.04 |
유니티 3D 게임 개발 - VFX 넣기 (1) | 2024.11.26 |
유니티 3D 게임 개발 - TPS 반동구현 (0) | 2024.11.26 |