#はじめに
Unityでセーブをする時に、PlayerPrefsでは、レジストリに保存されてしまうので、
ローカルに保存できるようにセーブファイルを作成する方法を模索しました。
参考にしていただければと思います。
#目次
- 流れ
- コード
- コードの説明
- Unityに設定
- 参考サイト
#流れ
ファイルを読み込む
↓
ファイルを保存する
↓
ファイルの値を反映する
#コード
必要なクラス
- SaveData
- GameData
- Save
- Read
- DataManager
###SaveData.cs
まずセーブするための項目を用意します
SaveData
[System.Serializable]
public class SaveData
{
public int numberInt;
public float numberFloat;
public string wordString;
public bool isDoingSomething;
}
###GameData.cs
ゲーム中で保持しておきたい項目を用意します
(初期の値は任意です)
GameData
public class GameData
{
public static int numberInt = 1;
public static float numberFloat = 1.5f;
public static string wordString = "Hellow";
public static bool isDoingSomething = true;
}
###Save.cs
データをファイルに保存します
Save
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
public class Save : MonoBehaviour
{
void OnEnable()
{
DoSave();
}
private void DoSave()
{
//セーブファイルのパスを設定
string SaveFilePath = Application.persistentDataPath + "/save.bytes";
// セーブデータの作成
SaveData saveData = CreateSaveData();
// セーブデータをJSON形式の文字列に変換
string jsonString = JsonUtility.ToJson(saveData);
// 文字列をbyte配列に変換
byte[] bytes = Encoding.UTF8.GetBytes(jsonString);
// AES暗号化
byte[] arrEncrypted = AesEncrypt(bytes);
// 指定したパスにファイルを作成
FileStream file = new FileStream(SaveFilePath, FileMode.Create, FileAccess.Write);
//ファイルに保存する
try
{
// ファイルに保存
file.Write(arrEncrypted, 0, arrEncrypted.Length);
}
finally
{
// ファイルを閉じる
if (file != null)
{
file.Close();
}
}
this.enabled = false;//このスクリプトをオフにする
}
// セーブデータの作成
private SaveData CreateSaveData()
{
//セーブデータのインスタンス化
SaveData saveData = new SaveData();
//ゲームデータの値をセーブデータに代入
saveData.numberInt = GameData.numberInt;
saveData.numberFloat = GameData.numberFloat;
saveData.wordString = GameData.wordString;
saveData.isDoingSomething = GameData.isDoingSomething;
return saveData;
}
/// AesManagedマネージャーを取得
private AesManaged GetAesManager()
{
//任意の半角英数16文字
string aesIv = "1234567890123456";
string aesKey = "1234567890123456";
AesManaged aes = new AesManaged();
aes.KeySize = 128;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.IV = Encoding.UTF8.GetBytes(aesIv);
aes.Key = Encoding.UTF8.GetBytes(aesKey);
aes.Padding = PaddingMode.PKCS7;
return aes;
}
/// AES暗号化
public byte[] AesEncrypt(byte[] byteText)
{
// AESマネージャーの取得
AesManaged aes = GetAesManager();
// 暗号化
byte[] encryptText = aes.CreateEncryptor().TransformFinalBlock(byteText, 0, byteText.Length);
return encryptText;
}
}
###Read.cs
ファイルのデータを読み込みます
Read
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
public class Read : MonoBehaviour
{
void OnEnable()
{
DoRead();
}
private void DoRead()
{
//セーブファイルのパスを設定
string SaveFilePath = Application.persistentDataPath + "/save.bytes";
//セーブファイルがあるか
if (File.Exists(SaveFilePath))
{
//ファイルモードをオープンにする
FileStream file = new FileStream(SaveFilePath, FileMode.Open, FileAccess.Read);
try
{
// ファイル読み込み
byte[] arrRead = File.ReadAllBytes(SaveFilePath);
// 復号化
byte[] arrDecrypt = AesDecrypt(arrRead);
// byte配列を文字列に変換
string decryptStr = Encoding.UTF8.GetString(arrDecrypt);
// JSON形式の文字列をセーブデータのクラスに変換
SaveData saveData = JsonUtility.FromJson<SaveData>(decryptStr);
//データの反映
ReadData(saveData);
}
finally
{
// ファイルを閉じる
if (file != null)
{
file.Close();
}
}
}
else
{
Debug.Log("セーブファイルがありません");
}
this.enabled = false;
}
//データの読み込み(反映)
private void ReadData(SaveData saveData)
{
GameData.numberInt = saveData.numberInt;
GameData.numberFloat = saveData.numberFloat;
GameData.wordString = saveData.wordString;
GameData.isDoingSomething = saveData.isDoingSomething;
}
/// AesManagedマネージャーを取得
private AesManaged GetAesManager()
{
//任意の半角英数16文字
string aesIv = "1234567890123456";
string aesKey = "1234567890123456";
AesManaged aes = new AesManaged();
aes.KeySize = 128;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.IV = Encoding.UTF8.GetBytes(aesIv);
aes.Key = Encoding.UTF8.GetBytes(aesKey);
aes.Padding = PaddingMode.PKCS7;
return aes;
}
/// AES復号化
public byte[] AesDecrypt(byte[] byteText)
{
// AESマネージャー取得
var aes = GetAesManager();
// 復号化
byte[] decryptText = aes.CreateDecryptor().TransformFinalBlock(byteText, 0, byteText.Length);
return decryptText;
}
}
###DataManager.cs
データをセーブしたり読み込んだりします
DataManager
using UnityEngine;
public class DataManager : MonoBehaviour
{
//クラスの参照
public Save saveClass;
public Read readClass;
void Start()
{
Read();
Save();
Read();
}
private void Read()
{
//読み込む
readClass.enabled = true;
Debug.Log("読み込みがおわりました");
}
private void Save()
{
//セーブする
saveClass.enabled = true;
Debug.Log("セーブができました");
}
}
#コードの説明
- SaveData.cs
セーブデータに入れるデータです。
[System.Serializable]を付けて、publicで変数を設定してください。
- GameData.cs
・ゲームの中で、常に持っておきたいデータです。
これは、変数にstaticを付けています。
データを読み込んで、各クラスの変数に代入する時には便利かと思います。
他に方法があると思いますので、参考程度にどうぞ。
- Save.cs
・データを保存するスクリプトです。
セーブデータの場所を設定
↓
セーブデータを作成
↓
Json形式に変換
↓
byte配列に変換
↓
AES暗号化
↓
指定したパスにファイルを作成
↓
ファイルを保存
↓
ファイルを閉じる
・セーブデータの場所はこちらになります。(PC)
C:\Users\User(ユーザーネーム)\AppData\LocalLow\DefaultCompany(プロジェクトカンパニー)\SampleForQiita(プロジェクトネーム)
- Read.cs
・データを読み込むスクリプトです。
セーブファイルの場所を設定
↓
セーブファイルがあるか確認
↓
ファイルモードをオープンにする
↓
byteのファイルを読み込み
↓
複合化
↓
byte配列を文字列に変換
↓
JSON形式の文字列をセーブデータのクラスに変換
↓
データを反映
↓
ファイルを閉じる
- DataManager.cs
・Unityで設定します
空のGameObjectを作成
↓
そこに、Read.cs、Save.cs、DataManager.csをアタッチします。
↓
DataManager(Script)のところに、Read.csとSave.csをアタッチします。
↓
Read.csとSave.csをOFFにしておきます
↓
エディターを再生します。図1
↓
C:\Users\User(ユーザーネーム)\AppData\LocalLow\DefaultCompany(プロジェクトカンパニー)\SampleForQiita(プロジェクトネーム)
にセーブファイルが作成されます。図2
↓
セーブデータの中身が暗号化されています。図3
#参考サイト
「Unity C# データを暗号化・復号化(AESとXOR)」 By @OnederAppli様
〇こちらの記事を書くにあたり、大変参考になりました。ありがとうございました。