2023. 12. 16. 01:08ㆍIT/TIL
오늘의 TIL의 내용은 스탠다드반 특강 때 배웠던 내용 중에서 데이터의 저장과 관련된 내용이다.
데이터의 저장
데이터의 저장은 직렬화(Serialization)이라는 과정을 거쳐서 저장하게된다.
직렬화란 객체를 Byte의 배열로 만드는 것으로,
우리가 프로그래밍한 복잡한 객체를 바이트들의 배열로 만드는 작업을 직렬화라고 하며,
모든 클래스를 직렬화할 수 있는 것은 아니다.
직렬화가 가능한 타입은 아래와 같다.
- 기본 데이터 형식(int, float, double, string, bool 등)
- 열거형 타입(Enum)
- Serializable 이라는 속성이 있는 구조체
- 특정 Unity 내장 타입 : Vector2,3,4, Rect, Quaternion, Color, Color32, LayerMask, Gradient, GUIStyle 등
데이터 파일을 저장하는 것이 좋은 이유는 아래와 같다.
즉, 프로그래머가 해야되는 작업을 다른 전문지식이 없는 사람이 작업할 수 있게 할 수 있으며,
코드가 아닌 엑셀 데이터나 Text 데이터를 수정함으로써 실제 게임의 데이터를 수정할 수 있으며,
추가 기능 구현이 자유로우며 안정성이 낮다는 장점이 있다.
데이터 저장방식
데이터 저장방식은 위의 이미지처럼
PlayerPrefs, CSV, JSON, SciptableObject, BinaryFormatter 등이 있다.
각 저장방식들은 장점과 단점이 있기 때문에 적절하게 사용하는 것이 좋다.
또, 프로젝트를 진행하면서 하나의 저장방식만을 사용하는 것이 아니라,
상황에 맞게 저장방식을 여러 종류를 사용할 수 있다.
PlayerPrefs
PlayerPrefs는 게임 세션 간에 플레이어 환경설정을 저장하는 클래스이다..
이 클래스는 문자열, 실수, 정수 값을 사용자의 플랫폼 레지스트리에 저장할 수 있다.
유니티는 암호화하지 않고 로컬 레지스트리에 PlayerPrefs를 저장한다.
민감한 데이터를 저장하는 데에는 적합하지 않다.
유니티는 어플리케이션이 실행되는 운영 체제에 따라 PlayerPrefs 데이터를 다르게 저장한다.
PlayerPrefs에는 아래와 같은 Method들이 존재하여 이를 활용하여 저장하고 삭제할 수 있다.
Static Methods
- DeleteAll
- DeleteKey
- GetFloat
- GetInt
- GetString
- HashKey
- Save
- SetFloat
- SetInt
- SetString
PlayerPrefs의 가장 큰 특징은 데이터를 암호화작업 없이 해당 컴퓨터의 레지스트리에 저장한다는 점이다.
즉, 레지스트리를 확인함으로써 데이터를 확인할 수 있고, 변경할 수 있다는 특징이 있다.
또, 해당 컴퓨터의 레지스트리에 저장되므로, 다른 컴퓨터에서는 해당 레지스트리를 받지않고는 값을 확인할 수 없다.
따라서 PlayerPrefs는 플레이어의 환경 설정(화면 크기, 음량 조절 등)을 저장하는데 사용하면 좋다.
또, 오락실에 있는 아케이드 게임기의 최고 점수 등을 기록하는 등에도 사용할 수 있다.
CSV(Comma-Separated Values)
CSV는 데이터를 저장하고 교환하는데 사용되는 간단한 파일 형식이다. 이 형식은 데이터 항목이 쉼표로 구분되며,
각 줄이 하나의 데이터 레코드를 나타낸다. CSV 파일은 엑셀이나 다른 표 계산 소프트웨어에서 쉽게 읽고 쓸 수 있으며,
프로그래밍에서도 널리 사용된다.
CSV를 사용하는데 가장 주의해야될 점은 데이터 값에 쉼표가 들어가면 안된다는 점이다.
쉼표를 통해서 데이터들의 항목이 구분되므로, 데이터 값에 쉼표가 들어가면
넣어주려던 데이터가 쉼표 앞까지 들어가게되고, 하나씩 항목이 밀리는 현상이 일어난다.
이를 해결할 수 있는 방법이 있지만 (예를 들면 |를 입력하면 데이터에 쉼표로 변경해주는 등의)
보편적으로는 CSV에는 쉼표를 넣지 않는 것을 기본으로 한다.
CSV는 보편적으로 데이터를 저장하는데 사용할 수 있는 방식이며,
그 값을 다른 소프트웨어(엑셀, 메모장 등)에서 읽을 수 있기에
데이터를 저장하는 경우에 가장 먼저 생각할 방법으로 사용할 수 있다.
JSON과 비교해서는 좀 더 가볍고 간단한 저장 방식이라고 할 수 있다.
JSON(JavaSript Object Notation)
JSON은 경량 데이터 교환 형식이다. 유니티에서는 JSON을 사용하여 데이터를 저장하고 읽어올 수 있다. JSON은 사람과 기계 모두에게 읽기 및 쓰기에 쉬운 형식이며, 다양한 프로그래밍 언어에서 지원된다.
JSON의 데이터는 Dictionary의 형식을 가지는 경우가 많으며,
이를 통해서 사람이 읽기도 편하고, 컴퓨터가 읽기 및 쓰기도 편해지는 효과를 준다.
JSON은 CSV와 마찬가지로 데이터를 저장하는데 사용하는 보편적인 방식이며,
그 값을 다른 소프트웨어(엑셀, 메모장 등)에서 읽을 수 있기에
데이터를 저장하는 경우에 가장 먼저 생각할 방법으로 사용할 수 있다.
CSV와 비교해서 Dictionary 형식으로 데이터를 저장하므로
비교적 파일이 무거워지는 단점이 있지만, 복잡한 데이터를 저장하는데 더 좋다는 장점이 있다.
SO(Scriptable Object)
SO는 유니티 엔진에서 사용되는 데이터 컨테이너로 이를 통해 게임 오브젝트나 씬에 종속되지 않고
데이터를 저장하고 공유할 수 있다. SO는 주로 게임의 리소스, 설정, 상태를 등리하는데 사용된다.
Box Collider, SriteRenderer 등 유니티의 기능들을 사용할 수 있다는 특징이 있으며,
유니티 에디터에서도 Inspector 창을 이용하여 데이터를 확인할 수 있다는 장점이 있다.
SO를 사용하는데 있어서 주의해야되는 점은
SO는 유니티 에디터를 통해서는 데이터 값을 변경하고 저장할 수 있지만, build된 게임에서는 값을 저장할 수 없기 때문에
SO를 사용하는 시점은 게임의 개발 시에 사용할 수 있으며, Build된 게임의 Develop 시점에서는 사용할 수 없다.
SO는 위의 설명에서 알 수 있듯이, 게임을 만드는 과정(Build하기 전)에서는 마음대로 사용할 수 있지만,
게임을 완성한 후에(Build한 후에) 수정해야되는 값을 저장하는데는 부적절하다는 단점이 있다.
하지만 SO는 유니티에서 지원하는 특별한 기능으로,
유니티 내에서 데이터를 확인할 수 있고, 유니티의 특정한 Component의 상태를 저장할 수 있다는 큰 장점이 있다.
Binary Formatter
Binary Formatter는 유니티에서 사용되는 직렬화 도구로, 이를 통해 객체를 이진 형식으로 직렬화하고, 이진 형식을 다시 객체로 역직렬화할 수 있다. Binary Formatter는 주로 파일 저장 및 로드에 사용되며, 데이터를 보다 효율적으로 관리하고 공유할 수 있다는 특징이 있다.
예를 들어 게임에서 플레이어의 상태를 저장하고 로드해야 할 때, Binary Formatter를 사용할 수 있다.
플레이어의 정보를 객체로 표현하고, 이를 이진 형식으로 직렬화하여 파일에 저장한다. 필요할 때마다 파일에서 이진 형식을 읽어와 역직렬화하여 플레이어의 정보를 복원한다.
Binary Formatter를 사용하기 위해서는 직렬화할 클래스에 [Serializable] 속성을 추가해야 한다. 또한, FileStream과 같은 파일 처리 클래스를 사용하여 파일을 생성하고 열어서 binary Formatter를 이용해 데이터를 읽고 쓸 수 있다.
Binary Formatter의 장점은 데이터를 이진화한다는 점인데,
이는 컴퓨터가 데이터를 저장하는데 자신에게 가장 편리한 방법을 사용한다는 점이다.
즉, 데이터를 저장하는데 가장 좋은 성능을 보여준다.
BinaryFormatter의 단점은 데이터를 이진 형식으로 저장하는 과정에서 데이터를 추가하는 것이 어렵다는 것인데,
특정 데이터를 모두 이진 형식으로 저장하면서 빈 공간을 따로 처리하지 않고 이진 형식으로 저장하기에
데이터를 변경하거나 추가하는 과정은 다른 방법과 다르게 어렵다고 할 수 있다.
총정리
컴퓨터에서 데이터를 저장하는 저장방식은 다양한 방식이 있으며,
주로 사용하는 방식은 PlayerPrefs, CSV, JSON, ScriptableObject, BinaryFormatter가 있다.
이 중에서 PlayerPrefs는 플레이어의 환경 설정을 저장하는데 사용하면 좋고,
CSV와 JSON은 보편적으로 플레이어의 데이터를 저장하는데 좋으며
ScriptableObject는 유니티에서의 특정 오브젝트들의 Component 상태를 저장하는데 좋다.
이러한 장단점들을 알고 데이터를 저장함으로써 게임의 데이터를 보다 효율적으로 관리할 수 있다.
단, 데이터를 로컬로 저장하는 것은 많은 문제점을 갖고 있으므로,
게임의 데이터를 관리하는 경우에는 서버를 통해서 관리하는 것이 좋다.
심한 경우에는 게임의 데이터가 변경되야되는 경우에는
무조건 서버로 그 데이터를 보내주어 서버에서 데이터를 처리한 후에 다시 보내주는 경우도 있다.
문제점
데이터를 자기 마음대로 변형하여 사용하는 경우로
작게는 데이터를 변형하여 치트를 사용하는 느낌으로 사용할 수 있지만,
심한 경우에는 해적판, 해킹판 등을 만들어서 유료재화를 무제한으로 만든 버전을 공유할 수 있다.
'IT > TIL' 카테고리의 다른 글
20231219_CherryPickCommit (0) | 2023.12.21 |
---|---|
20231218_OnTrigger,OnCollision (0) | 2023.12.19 |
20231214_프리펩,ItemSlot (0) | 2023.12.14 |
20231213_Class (0) | 2023.12.14 |
20231212_ScriptableObject (0) | 2023.12.12 |