상세 컨텐츠

본문 제목

유니티 캐릭터 위치 그대로 저장하고 불러오기

유니티/기능

by MJ_119 2024. 9. 25. 17:15

본문

- 캐릭터 위치를 바이너리 파일로 바꿔서 저장 및 불러오기

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class SaveSystem : MonoBehaviour
{
    // 매 프레임마다 키 입력을 체크하여 S 또는 L을 누르면 각각 저장 또는 불러오기 함수 호출
    private void Update()
    {
        // S 키를 누르면 'save'라는 이름의 파일로 저장
        if (Input.GetKeyDown(KeyCode.S))
        {
            Save("save");
        }
        // L 키를 누르면 'save'라는 이름의 파일에서 데이터 불러오기
        if (Input.GetKeyDown(KeyCode.L))
        {
            Load("save");
        }
    }

    // 데이터를 저장하는 함수
    public void Save(string saveFile)
    {
        // 파일 저장 경로를 생성
        string path = GetPathFromSaveFile(saveFile);
        print("Save : " + path);  // 저장 경로를 출력

        // 지정한 경로에 파일을 생성하고 데이터를 씀
        using (FileStream stream = File.Open(path, FileMode.Create))
        {
            // 플레이어의 Transform(위치, 회전 등) 컴포넌트를 가져옴
            Transform playerTransform = GetPlayerTransform();

            // 플레이어의 현재 위치 정보를 byte 배열로 변환
            byte[] buffer = SerializeVector(playerTransform.position);

            // byte 배열을 파일에 씀
            stream.Write(buffer, 0, buffer.Length);
        }
    }

    // 데이터를 불러오는 함수
    public void Load(string saveFile)
    {
        // 불러올 파일의 경로를 생성
        string path = GetPathFromSaveFile(saveFile);
        print("Load : " + path);  // 불러올 파일 경로를 출력

        // 파일을 열어서 데이터를 읽음
        using (FileStream stream = File.Open(path, FileMode.Open))
        {
            // 파일 크기만큼의 byte 배열을 생성
            byte[] buffer = new byte[stream.Length];

            // 파일에서 데이터를 읽어서 byte 배열에 저장
            stream.Read(buffer, 0, buffer.Length);

            // 플레이어의 Transform 컴포넌트를 가져와서
            Transform playerTransform = GetPlayerTransform();

            // 불러온 데이터를 Vector3로 변환한 후, 플레이어의 위치를 해당 좌표로 설정
            playerTransform.position = DeSerialzeVector(buffer);
        }
    }

    // Vector3 데이터를 byte 배열로 변환하는 함수
    private byte[] SerializeVector(Vector3 vector)
    {
        // 각 좌표(x, y, z)를 4바이트 float로 변환하여 byte 배열에 저장 (3개의 좌표값 * 4바이트)
        byte[] vectorBytes = new byte[3 * 4];
        BitConverter.GetBytes(vector.x).CopyTo(vectorBytes, 0);
        BitConverter.GetBytes(vector.y).CopyTo(vectorBytes, 4);
        BitConverter.GetBytes(vector.z).CopyTo(vectorBytes, 8);
        return vectorBytes;
    }

    // byte 배열을 Vector3로 변환하는 함수
    Vector3 DeSerialzeVector(byte[] buffer)
    {
        Vector3 result = new Vector3();
        // byte 배열의 처음 4바이트는 x 좌표, 그다음 4바이트는 y, 그다음 4바이트는 z 좌표
        result.x = BitConverter.ToSingle(buffer, 0);
        result.y = BitConverter.ToSingle(buffer, 4);
        result.z = BitConverter.ToSingle(buffer, 8);
        return result;
    }

    // 'Player' 태그를 가진 게임 오브젝트의 Transform을 반환
    private Transform GetPlayerTransform()
    {
        return GameObject.FindWithTag("Player").transform;
    }

    // 지정한 파일 이름에 대한 파일 경로를 반환 (저장 경로를 플랫폼에 맞춰 설정)
    string GetPathFromSaveFile(string saveFile)
    {
        // Application.persistentDataPath는 각 플랫폼에 맞는 저장 경로를 제공
        return Path.Combine(Application.persistentDataPath, saveFile + ".sav");
    }
}

 

 

 

- 더 나은 방법

 

SerializableVector3:

  • Unity의 Vector3는 기본적으로 직렬화가 불가능하므로, 이를 감싸는 SerializableVector3 클래스를 만들고 사용하여 직렬화 및 역직렬화를 지원합니다.

 

파일1. SaveSystem.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
using UnityEngine.UIElements;

public class SaveSystem : MonoBehaviour
{
    // 매 프레임마다 키 입력을 체크하여 S 또는 L을 누르면 각각 저장 또는 불러오기 함수 호출
    private void Update()
    {
        // S 키를 누르면 'save'라는 이름의 파일로 저장
        if (Input.GetKeyDown(KeyCode.S))
        {
            Save("save"); // 'save' 파일로 저장
        }
        // L 키를 누르면 'save'라는 이름의 파일에서 데이터 불러오기
        if (Input.GetKeyDown(KeyCode.L))
        {
            Load("save"); // 'save' 파일에서 데이터 로드
        }
    }

    // 데이터를 저장하는 함수
    public void Save(string saveFile)
    {
        // 파일 저장 경로를 생성
        string path = GetPathFromSaveFile(saveFile);
        print("Save : " + path);  // 저장 경로를 콘솔에 출력

        // 파일을 생성하고 데이터를 쓰기 위한 FileStream 열기
        using (FileStream stream = File.Open(path, FileMode.Create))
        {
            // 플레이어의 Transform 컴포넌트(위치, 회전 등) 가져오기
            Transform playerTransform = GetPlayerTransform();

            // 이진 형식으로 객체를 직렬화하기 위한 BinaryFormatter 생성
            BinaryFormatter formatter = new BinaryFormatter();

            // 플레이어의 위치 정보를 직렬화 가능한 형태로 변환
            SerializableVector3 position = new SerializableVector3(playerTransform.position);

            // 변환된 데이터를 이진 형식으로 파일에 저장
            formatter.Serialize(stream, position);
        }
    }

    // 데이터를 불러오는 함수
    public void Load(string saveFile)
    {
        // 불러올 파일의 경로를 생성
        string path = GetPathFromSaveFile(saveFile);
        print("Load : " + path);  // 불러올 파일 경로를 콘솔에 출력

        // 파일을 열어서 데이터를 읽기 위한 FileStream 열기
        using (FileStream stream = File.Open(path, FileMode.Open))
        {
            // 플레이어의 Transform 컴포넌트 가져오기
            Transform playerTransform = GetPlayerTransform();

            // 이진 데이터를 역직렬화하기 위한 BinaryFormatter 생성
            BinaryFormatter formatter = new BinaryFormatter();

            // 파일로부터 직렬화된 데이터를 역직렬화하여 플레이어의 위치 정보로 변환
            SerializableVector3 position = (SerializableVector3)formatter.Deserialize(stream);

            // 플레이어의 위치를 불러온 데이터로 설정
            playerTransform.position = position.ToVector();
        }
    }

    // 'Player' 태그를 가진 게임 오브젝트의 Transform을 반환
    private Transform GetPlayerTransform()
    {
        // 'Player' 태그로 게임 오브젝트를 찾아 Transform 컴포넌트를 반환
        return GameObject.FindWithTag("Player").transform;
    }

    // 지정한 파일 이름에 대한 파일 경로를 반환 (저장 경로를 플랫폼에 맞게 설정)
    string GetPathFromSaveFile(string saveFile)
    {
        // Application.persistentDataPath는 각 플랫폼에 맞는 저장 경로를 제공
        return Path.Combine(Application.persistentDataPath, saveFile + ".sav");
    }
}

// 직렬화를 위해 Vector3를 감싸는 Serializable 클래스 정의
[Serializable]
public class SerializableVector3
{
    public float x, y, z;

    // 생성자를 통해 Vector3를 SerializableVector3로 변환
    public SerializableVector3(Vector3 vector)
    {
        x = vector.x;
        y = vector.y;
        z = vector.z;
    }

    // SerializableVector3를 다시 Unity의 Vector3로 변환
    public Vector3 ToVector()
    {
        return new Vector3(x, y, z);
    }
}

 

파일2. SerializableVector3.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class SerializableVector3
{
    float x, y, z;

    public SerializableVector3(Vector3 vector)
    {
        x = vector.x; 
        y = vector.y; 
        z = vector.z;
    }

    public Vector3 ToVector()
    {
        return new Vector3(x, y, z);
    }
}

 

 

 

 

관련글 더보기