こんにちは uni928 です。
皆さんは PlayerPrefs を使用する機会はありますか?
私はほとんどありませんが
プログラミング初心者の方には使いやすい
機能だと思います。
Unity を習得する際も
PlayerPrefs で練習するのは
多くの人が通る道ではないでしょうか?
そうでもないでしょうか?
しかしながら PlayerPrefs は
string int float しか保存する事はできません。
そこで PlayerPrefs に
任意の型を保存する拡張を
提供したいと思います。
Unity 習得中の人も
是非導入して頂けると幸いです。
https://drive.google.com/file/d/1KFfQqLLjSHW8_n1Mr5V9bPV-a_K7ye31/view?usp=sharing
unitypackage 版は
上記の URL からダウンロードして下さい。
SephirothPlayerPrefsExtension.cs
以外のファイルは削除してかまいません。
HowToUse.pdf 等は容量が大きいため
削除する事を推奨します。
では仕組みを作成していきます。
SephirothPlayerPrefsExtension.cs を作成して
下記の内容にして下さい。
using System.Security.Cryptography;
namespace SephirothTools
{
public static class SephirothPlayerPrefsExtension
{
private static readonly System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
private static readonly System.IO.MemoryStream ms = new System.IO.MemoryStream();
public static void Save<T>(string key, T value)
{
ms.Position = 0;
ms.SetLength(0);
formatter.Serialize(ms, value);
UnityEngine.PlayerPrefs.SetString(key, System.Convert.ToBase64String(Encrypt(ms.ToArray())));
}
public static T Load<T>(string key, T defaultValue = default)
{
string loadValue = UnityEngine.PlayerPrefs.GetString(key, "");
if (string.IsNullOrEmpty(loadValue))
{
return defaultValue;
}
byte[] bytes = Decrypt(System.Convert.FromBase64String(loadValue));
ms.Position = 0;
ms.Write(bytes, 0, bytes.Length);
ms.Position = 0;
return (T)formatter.Deserialize(ms);
}
private const string AesIV = @"kgificpplgodckdi"; // Declare a random string of 16 single-byte characters.
private const string AesKey = @"lfsaokfdsjhahfppjdfjshfsdgssdfas"; // Declare a random string of 32 single-byte characters.
private const int KeySize = 256;
private const int BlockSize = 128;
private static byte[] Encrypt(byte[] byteValue)
{
return GetAes().CreateEncryptor().TransformFinalBlock(byteValue, 0, byteValue.Length);
}
private static byte[] Decrypt(byte[] byteValue)
{
return GetAes().CreateDecryptor().TransformFinalBlock(byteValue, 0, byteValue.Length);
}
private static AesManaged GetAes()
{
var aes = new AesManaged();
aes.KeySize = KeySize;
aes.BlockSize = BlockSize;
aes.Mode = CipherMode.CBC;
aes.IV = System.Text.Encoding.UTF8.GetBytes(AesIV);
aes.Key = System.Text.Encoding.UTF8.GetBytes(AesKey);
aes.Padding = PaddingMode.PKCS7;
return aes;
}
}
}
PlayerPrefs.SetString("key1", value);
の代わりに
SephirothTools.SephirothPlayerPrefsExtension.Save<string>("key1", value);
を使用します。
PlayerPrefs.GetString("key1");
の代わりに
SephirothTools.SephirothPlayerPrefsExtension.Load<string>("key1");
を使用します。
多くの型を保存できるため
SephirothTools.SephirothPlayerPrefsExtension.Save<List<int>>("key2", new List(){1, 2, 3});
List<int> loadList = SephirothTools.SephirothPlayerPrefsExtension.Load<List<int>>("key2");
のような記述もできます。
Save<T> Load<T> の T の部分に
保存する型を入れる事で使用できます。
暗号化に関しては
直接書いてしまっているため
逆コンパイルに対応できません。
おまじない程度の認識でお願いします。
暗号化しても速度がほとんど変わらないため
やる意味は薄くても記述する価値があります。
あとがき
以上が PlayerPrefs に
任意の型を保存する仕組みになります。
PlayerPrefs の代わりに
SephirothTools.SephirothPlayerPrefsExtension.Save
SephirothTools.SephirothPlayerPrefsExtension.Load
を使用するだけなので
使用するのは簡単だと思います。
この仕組みが
皆さんの開発の助けになれば幸いです。
閲覧ありがとうございました。