Use when implementing, documenting, or troubleshooting Storage workflows in F8Framework, including local persistence, user-scoped keys, AES encryption, Gzip compression, generic collections, and common Unity value types.
4c:T1e06,
⚠️ IMPORTANT: Before using this feature, you MUST formally initialize F8Framework in the launch sequence. Ensure
ModuleCenter.Initialize(this);has run first, then create the required module, for exampleFF8.Storage = ModuleCenter.CreateModule<StorageManager>();.
FF8.Storage, StorageManager, AES encryption, compression, or file-based save operations.Assets/F8Framework/Runtime/Storage.Assets/F8Framework/Tests/Storage.Assets/F8Framework/Tests/Storage/DemoStorage.csAssets/F8Framework/Tests/Storage/README.mdAssets/F8Framework/Tests/Storage/README_EN.mdAssets/F8Framework/Runtime/Storage/StorageManager.csAssets/F8Framework/Tests/Storage| Class | Role |
|---|---|
StorageManager | Core storage module, accessed via FF8.Storage. |
StorageManager.Settings | Runtime storage configuration. |
Util.OptimizedAES | AES configuration used by StorageManager. |
StorageManager before first storage access.SetUser() first.Save() after writes in File mode.FF8.Storage.Configure(new StorageManager.Settings
{
location = StorageManager.Location.File,
directory = StorageManager.Directory.PersistentDataPath,
defaultFilePath = "Save/PlayerData.json",
compressionType = StorageManager.CompressionType.Gzip,
encryption = new Util.OptimizedAES(key: "AES_Key", iv: null)
});
FF8.Storage.SetUser("User_10001");
// Primitive types
FF8.Storage.SetString("nickname", "F8Player", user: true);
FF8.Storage.SetInt("coins", 2560);
FF8.Storage.SetFloat("music_volume", 0.75f);
FF8.Storage.SetBool("guide_finished", true);
// Extended numeric types
FF8.Storage.SetChar("grade", 'S');
FF8.Storage.SetByte("byte_value", 128);
FF8.Storage.SetShort("short_value", 1024);
FF8.Storage.SetLong("long_value", 9876543210L);
FF8.Storage.SetDouble("double_value", 12.3456789d);
FF8.Storage.SetDecimal("decimal_value", 99.99m);
FF8.Storage.SetSByte("sbyte_value", -12);
FF8.Storage.SetUShort("ushort_value", 65530);
FF8.Storage.SetUInt("uint_value", 1234567890U);
FF8.Storage.SetULong("ulong_value", 1234567890123456789UL);
// Enum and tuple
FF8.Storage.SetEnum("save_mode", SaveMode.Hardcore);
FF8.Storage.SetValueTuple("tuple2", (1, "tuple"));
FF8.Storage.SetValueTuple("tuple7", (1, 2, 3, 4, 5, 6, 7));
// Object and collections
FF8.Storage.SetObject("profile", profile);
FF8.Storage.Set("int_array", new[] { 1, 2, 3, 4 });
FF8.Storage.SetList("string_list", new List<string> { "A", "B", "C" });
FF8.Storage.SetDictionary("map", new Dictionary<int, string> { { 1, "one" } });
FF8.Storage.SetQueue("queue", new Queue<int>(new[] { 10, 20, 30 }));
FF8.Storage.SetHashSet("hashset", new HashSet<string> { "fire", "ice" });
FF8.Storage.SetStack("stack", new Stack<int>(new[] { 7, 8, 9 }));
FF8.Storage.SetRectangularArray("grid", new int[,] { { 1, 2 }, { 3, 4 } });
FF8.Storage.SetJaggedArray("jagged", new int[][] { new[] { 1, 2 }, new[] { 3, 4, 5 } });
// Unity types currently exposed by StorageManager.cs
FF8.Storage.SetVector2("vector2", new Vector2(1.5f, 2.5f));
FF8.Storage.SetVector3("vector3", new Vector3(3f, 4f, 5f));
FF8.Storage.SetVector4("vector4", new Vector4(6f, 7f, 8f, 9f));
FF8.Storage.SetVector2Int("vector2int", new Vector2Int(10, 11));
FF8.Storage.SetVector3Int("vector3int", new Vector3Int(12, 13, 14));
FF8.Storage.SetQuaternion("rotation", Quaternion.Euler(15f, 30f, 45f));
FF8.Storage.SetColor("color", new Color(0.1f, 0.2f, 0.3f, 1f));
FF8.Storage.SetColor32("color32", new Color32(10, 20, 30, 255));
FF8.Storage.SetMatrix4x4("matrix", Matrix4x4.identity);
FF8.Storage.SetBounds("bounds", new Bounds(Vector3.zero, Vector3.one * 2));
FF8.Storage.SetRect("rect", new Rect(5f, 10f, 100f, 50f));
FF8.Storage.SetRectOffset("rect_offset", new RectOffset(1, 2, 3, 4));
FF8.Storage.SetLayerMask("layer_mask", (LayerMask)(1 << 8));
// Save / remove / clear
FF8.Storage.Save();
FF8.Storage.Save("Save/PlayerData.backup.json");
FF8.Storage.Remove("coins", filePath: "Save/PlayerData.backup.json");
FF8.Storage.Clear("Save/TempPlayerData.json");
PlayerPrefsFileResources (read-only at runtime)NoneGzipstring, int, float, boolchar, byte, short, long, double, decimalsbyte, ushort, uint, ulongGet<T>/Set<T>GetObject<T>/SetObject<T>GetEnum<TEnum>/SetEnum<TEnum>GetValueTuple/SetValueTuple for 1 to 7 itemsListDictionaryQueueHashSetStackStorageManager:
Vector2Vector3Vector4Vector2IntVector3IntQuaternionColorColor32Matrix4x4BoundsRectRectOffsetLayerMaskStorageManager.Settings.SetObject/GetObject for plain data classes.Save() after writes when using file storage.SetObject/GetObject may behave differently in player builds if deserialization falls back to reflection-based property assignment.StorageManagerSetObject| Problem | Likely cause | Recommended fix |
|---|---|---|
| Data not persisted | Save() was not called in file mode | Call Save() after writes |
| User data overlaps | SetUser() missing before user-scoped keys | Set user id first |
| Read/write mismatch | Storage configured after first access | Configure before any storage usage |
| Decryption fails | AES key changed between sessions | Keep encryption config stable |
| Queue or Stack shape is wrong | LitJson collection support mismatch | Check JsonMapper.g.cs collection handling |
| Unity type works in editor but fails in build | Reflection-based value-type deserialization | Use DTO or primitive-component storage |