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차적으로 데이터 조작을 막습니다. 또한 데이터 매니저를 통해 서버에서 데이터를 받아 사용자가 조작하지 못하도록 방지하기도 합니다. (데이터 매니저 구현 방법을 알고싶다면 링크를 클릭해주세요.)

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다