PlayerPrefs는 유니티에서 데이터를 저장하기 쉽도록 제공해주는 기능입니다. 장단점을 파악하여 사용하면 용도에 맞게 잘 사용할 수 있지만, 자칫 잘못 사용하면 보안 문제나, 데이터가 날아가 버리거나 하는 문제들이 생깁니다. 이번 시간은 PlayerPrefs가 무엇인지 알아보고, 장점과 단점 및 용도를 배워 보겠습니다. 또한 실제로 사용해 보고 예시코드까지 제공하겠습니다.
목차
[PlayerPrefs의 개념]
데이터를 저장하고 로드하기 위한 기능 입니다. 키-값 쌍으로 데이터를 저장하며, 문자열 키를 사용하여 식별한 데이터를 가져옵니다.
// 데이터 저장
PlayerPrefs.SetInt("Score", 100);
PlayerPrefs.SetString("PlayerName", "John");
// 데이터 로드
int score = PlayerPrefs.GetInt("Score");
string playerName = PlayerPrefs.GetString("PlayerName");
위 코드는 데이터를 저장하고 로드하는 간단한 예시 입니다.
[PlayerPrefs의 사용법]
[저장하기]
// 정수 값 저장
int score = 100;
PlayerPrefs.SetInt("Score", score);
// 문자열 값 저장
string playerName = "John";
PlayerPrefs.SetString("PlayerName", playerName);
// 부동 소수점 값 저장
float playerHealth = 80.5f;
PlayerPrefs.SetFloat("PlayerHealth", playerHealth);
// 불리언 값 저장
bool isGameCompleted = true;
PlayerPrefs.SetInt("IsGameCompleted", isGameCompleted ? 1 : 0);
[로드 하기]
// 정수 값 로드
int loadedScore = PlayerPrefs.GetInt("Score");
// 문자열 값 로드
string loadedPlayerName = PlayerPrefs.GetString("PlayerName");
// 부동 소수점 값 로드
float loadedPlayerHealth = PlayerPrefs.GetFloat("PlayerHealth");
// 불리언 값 로드
bool loadedIsGameCompleted = PlayerPrefs.GetInt("IsGameCompleted") == 1 ? true : false;
[삭제하기]
// 특정 키의 데이터 삭제
PlayerPrefs.DeleteKey("Score");
// 모든 데이터 삭제
PlayerPrefs.DeleteAll();
[PlayerPrefs의 장점과 단점]
[장점]
- 데이터를 저장하고 로드 하는 것이 간단합니다.
- 간단하기에 기능을 익히는데 어려움이 없습니다.
[단점]
- 보안에 취약합니다. 로컬에 저장하다 보니 사용자가 데이터를 바꾸는 것이 매우 쉽습니다.
- 이러한 단점을 보완하기 위해서 암호화를 한다고 하여도 로컬에 저장되기 때문에 취약할 수 밖에 없습니다.
- 로컬에 저장하기 때문에 컴퓨터를 포맷하거나, 핸드폰의 기기를 변경하는 경우 사용자의 데이터가 전부 날아가 버립니다.
[언제 사용해야 할까?]
- 간단한 설정 및 상태를 저장
- 음악과 효과음등의 볼륨 크기
- 캐릭터의 프리셋
- 현재 사용하는 언어
- 그래픽 품질 설정
[음악과 효과음의 볼륨 크기 저장 예시코드]
using UnityEngine;
public class SoundSettings : MonoBehaviour
{
public AudioSource musicSource; // 음악을 재생하는 AudioSource
public AudioSource soundEffectsSource; // 효과음을 재생하는 AudioSource
private float defaultMusicVolume = 0.7f; // 기본 음악 볼륨
private float defaultSoundEffectsVolume = 0.8f; // 기본 효과음 볼륨
void Start()
{
// PlayerPrefs에서 저장된 볼륨 크기 불러오기, 저장된 값이 없으면 기본 값 사용
float savedMusicVolume = PlayerPrefs.GetFloat("MusicVolume", defaultMusicVolume);
float savedSoundEffectsVolume = PlayerPrefs.GetFloat("SoundEffectsVolume", defaultSoundEffectsVolume);
// 음악 볼륨 설정
musicSource.volume = savedMusicVolume;
// 효과음 볼륨 설정
soundEffectsSource.volume = savedSoundEffectsVolume;
}
// 음악 볼륨 설정
public void SetMusicVolume(float volume)
{
musicSource.volume = volume;
// PlayerPrefs에 음악 볼륨 저장
PlayerPrefs.SetFloat("MusicVolume", volume);
}
// 효과음 볼륨 설정
public void SetSoundEffectsVolume(float volume)
{
soundEffectsSource.volume = volume;
// PlayerPrefs에 효과음 볼륨 저장
PlayerPrefs.SetFloat("SoundEffectsVolume", volume);
}
}
[캐릭터의 프리셋 저장 예시코드]
using UnityEngine;
public class CharacterPreset : MonoBehaviour
{
// 캐릭터의 이름을 입력받는 InputField
public TMPro.TMP_InputField nameInputField;
// 캐릭터의 외형을 선택하는 Dropdown
public UnityEngine.UI.Dropdown appearanceDropdown;
private void Start()
{
// 저장된 캐릭터 프리셋 불러오기
LoadCharacterPreset();
}
// 캐릭터 프리셋 저장
public void SaveCharacterPreset()
{
// 캐릭터의 이름 저장
string characterName = nameInputField.text;
PlayerPrefs.SetString("CharacterName", characterName);
// 캐릭터의 외형 인덱스 저장
int appearanceIndex = appearanceDropdown.value;
PlayerPrefs.SetInt("AppearanceIndex", appearanceIndex);
// PlayerPrefs 변경사항을 저장
PlayerPrefs.Save();
}
// 저장된 캐릭터 프리셋 불러오기
public void LoadCharacterPreset()
{
// 저장된 캐릭터의 이름 불러오기, 저장된 값이 없으면 기본값 사용
string savedCharacterName = PlayerPrefs.GetString("CharacterName", "DefaultName");
nameInputField.text = savedCharacterName;
// 저장된 캐릭터의 외형 인덱스 불러오기, 저장된 값이 없으면 기본값 사용
int savedAppearanceIndex = PlayerPrefs.GetInt("AppearanceIndex", 0);
appearanceDropdown.value = savedAppearanceIndex;
}
}
캐릭터의 외형이나 이름등 저장된 프리셋이 있다면 사용하는 코드 입니다.
[현재 사용하는 언어 저장 예시코드]
using UnityEngine;
public enum Language
{
Korean,
English,
Japanese
}
public class LanguageSettings : MonoBehaviour
{
// 사용자가 선택할 수 있는 언어 목록
public UnityEngine.UI.Dropdown languageDropdown;
void Start()
{
// 저장된 언어 설정 불러오기, 저장된 값이 없으면 기본값으로 설정
Language savedLanguage = (Language)PlayerPrefs.GetInt("Language", (int)Language.English);
languageDropdown.value = (int)savedLanguage;
// 언어 설정 적용
ApplyLanguage(savedLanguage);
}
// 언어 설정 변경
public void SetLanguage(int languageIndex)
{
Language selectedLanguage = (Language)languageIndex;
// 선택한 언어를 PlayerPrefs에 저장
PlayerPrefs.SetInt("Language", (int)selectedLanguage);
PlayerPrefs.Save();
// 언어 설정 적용
ApplyLanguage(selectedLanguage);
}
// 언어 설정 적용
private void ApplyLanguage(Language language)
{
// 언어에 따라 다른 처리
switch (language)
{
case Language.Korean:
// 한국어로 변경
Debug.Log("한국어로 변경됨");
break;
case Language.English:
// 영어로 변경
Debug.Log("English language selected");
break;
case Language.Japanese:
// 일본어로 변경
Debug.Log("日本語に変更されました");
break;
}
}
}
대체적으로 핵심적인 데이터를 저장하는 것이 아닌 설정의 관련된 것을 저장하는데 사용됩니다.
캐릭터의 재화나 레벨 등을 저장하게 되면 보안에 취약하기에 사용자가 직접 바꿀 수 있고, 로컬에 저장하다 보니 데이터가 날아갈 위협 때문에 그렇습니다.
[마무리 글]
용도를 알고 사용하면 정말 편리한 기능입니다. 하지만 편리하다고 하여 모든 데이터를 저장하게 되면 보안의 취약성으로 인해서 프로젝트의 큰 손해를 입히기도 합니다. 그렇기에 암호화를 사용하여 1차적으로 데이터 조작을 막습니다. 또한 데이터 매니저를 통해 서버에서 데이터를 받아 사용자가 조작하지 못하도록 방지하기도 합니다. (데이터 매니저 구현 방법을 알고싶다면 링크를 클릭해주세요.)