copy from github
This commit is contained in:
8
Tests/Editor.meta
Normal file
8
Tests/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ff28f3695e4c214d9f9c9d3f14e2259
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Tests/Editor/Jovian.SaveSystem.EditorTests.asmdef
Normal file
24
Tests/Editor/Jovian.SaveSystem.EditorTests.asmdef
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "Jovian.SaveSystem.EditorTests",
|
||||
"rootNamespace": "Jovian.SaveSystem.Tests.Editor",
|
||||
"references": [
|
||||
"Jovian.SaveSystem",
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Tests/Editor/Jovian.SaveSystem.EditorTests.asmdef.meta
Normal file
7
Tests/Editor/Jovian.SaveSystem.EditorTests.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e61712a36e316da4b9cd50d3d5ae71bc
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
104
Tests/Editor/SaveSerializerTests.cs
Normal file
104
Tests/Editor/SaveSerializerTests.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Jovian.SaveSystem.Tests.Editor {
|
||||
public class SaveSerializerTests {
|
||||
[Serializable]
|
||||
private sealed class TestData {
|
||||
public string name;
|
||||
public int score;
|
||||
public float[] positions;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonSerializer_RoundTrip_PreservesData() {
|
||||
JsonSaveSerializer serializer = new JsonSaveSerializer();
|
||||
TestData original = new TestData {
|
||||
name = "TestPlayer",
|
||||
score = 42,
|
||||
positions = new[] { 1.5f, 2.5f, 3.5f }
|
||||
};
|
||||
|
||||
byte[] bytes = serializer.Serialize(original);
|
||||
TestData deserialized = serializer.Deserialize<TestData>(bytes);
|
||||
|
||||
Assert.AreEqual(original.name, deserialized.name);
|
||||
Assert.AreEqual(original.score, deserialized.score);
|
||||
Assert.AreEqual(original.positions, deserialized.positions);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonSerializer_ProducesNonEmptyBytes() {
|
||||
JsonSaveSerializer serializer = new JsonSaveSerializer();
|
||||
TestData data = new TestData { name = "Test", score = 1 };
|
||||
|
||||
byte[] bytes = serializer.Serialize(data);
|
||||
|
||||
Assert.IsNotNull(bytes);
|
||||
Assert.Greater(bytes.Length, 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonSerializer_DeserializeNull_Throws() {
|
||||
JsonSaveSerializer serializer = new JsonSaveSerializer();
|
||||
|
||||
Assert.Throws<ArgumentException>(() => serializer.Deserialize<TestData>(null));
|
||||
Assert.Throws<ArgumentException>(() => serializer.Deserialize<TestData>(Array.Empty<byte>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BinarySerializer_RoundTrip_PreservesData() {
|
||||
BinarySaveSerializer serializer = new BinarySaveSerializer("test-key-123");
|
||||
TestData original = new TestData {
|
||||
name = "BinaryPlayer",
|
||||
score = 99,
|
||||
positions = new[] { 10f, 20f, 30f }
|
||||
};
|
||||
|
||||
byte[] bytes = serializer.Serialize(original);
|
||||
TestData deserialized = serializer.Deserialize<TestData>(bytes);
|
||||
|
||||
Assert.AreEqual(original.name, deserialized.name);
|
||||
Assert.AreEqual(original.score, deserialized.score);
|
||||
Assert.AreEqual(original.positions, deserialized.positions);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BinarySerializer_OutputDiffersFromJson() {
|
||||
JsonSaveSerializer jsonSerializer = new JsonSaveSerializer();
|
||||
BinarySaveSerializer binarySerializer = new BinarySaveSerializer("test-key");
|
||||
TestData data = new TestData { name = "Test", score = 1 };
|
||||
|
||||
byte[] jsonBytes = jsonSerializer.Serialize(data);
|
||||
byte[] binaryBytes = binarySerializer.Serialize(data);
|
||||
|
||||
Assert.AreNotEqual(jsonBytes, binaryBytes);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BinarySerializer_DifferentKeys_ProduceDifferentOutput() {
|
||||
BinarySaveSerializer serializer1 = new BinarySaveSerializer("key-alpha");
|
||||
BinarySaveSerializer serializer2 = new BinarySaveSerializer("key-bravo");
|
||||
TestData data = new TestData { name = "Test", score = 1 };
|
||||
|
||||
byte[] bytes1 = serializer1.Serialize(data);
|
||||
byte[] bytes2 = serializer2.Serialize(data);
|
||||
|
||||
Assert.AreNotEqual(bytes1, bytes2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BinarySerializer_EmptyKey_Throws() {
|
||||
Assert.Throws<ArgumentException>(() => new BinarySaveSerializer(""));
|
||||
Assert.Throws<ArgumentException>(() => new BinarySaveSerializer(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BinarySerializer_DeserializeNull_Throws() {
|
||||
BinarySaveSerializer serializer = new BinarySaveSerializer("key");
|
||||
|
||||
Assert.Throws<ArgumentException>(() => serializer.Deserialize<TestData>(null));
|
||||
Assert.Throws<ArgumentException>(() => serializer.Deserialize<TestData>(Array.Empty<byte>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Tests/Editor/SaveSerializerTests.cs.meta
Normal file
2
Tests/Editor/SaveSerializerTests.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e16fa5e1d6fe1240bbb82bbb338cec3
|
||||
150
Tests/Editor/SaveSlotManagerTests.cs
Normal file
150
Tests/Editor/SaveSlotManagerTests.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Jovian.SaveSystem.Tests.Editor {
|
||||
public class SaveSlotManagerTests {
|
||||
private InMemorySaveStorage storage;
|
||||
private SaveSystemSettings settings;
|
||||
private SaveSlotManager slotManager;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {
|
||||
storage = new InMemorySaveStorage();
|
||||
settings = new SaveSystemSettings { maxAutoSavesPerSession = 3 };
|
||||
slotManager = new SaveSlotManager(storage, settings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateSession_ReturnsNonEmptyId() {
|
||||
string sessionId = slotManager.CreateSession();
|
||||
|
||||
Assert.IsNotNull(sessionId);
|
||||
Assert.IsNotEmpty(sessionId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateSession_AppearsInAllSessions() {
|
||||
string sessionId = slotManager.CreateSession();
|
||||
|
||||
IReadOnlyList<SaveSessionInfo> sessions = slotManager.GetAllSessions();
|
||||
|
||||
Assert.AreEqual(1, sessions.Count);
|
||||
Assert.AreEqual(sessionId, sessions[0].sessionId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllocateManualSlot_IncrementsSlotNumber() {
|
||||
string sessionId = slotManager.CreateSession();
|
||||
|
||||
SaveSlotInfo slot1 = slotManager.AllocateManualSlot(sessionId);
|
||||
SaveSlotInfo slot2 = slotManager.AllocateManualSlot(sessionId);
|
||||
|
||||
Assert.AreEqual(1, slot1.slotNumber);
|
||||
Assert.AreEqual(2, slot2.slotNumber);
|
||||
Assert.AreEqual(SaveSlotType.Manual, slot1.slotType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllocateAutoSlot_RotatesWhenMaxReached() {
|
||||
string sessionId = slotManager.CreateSession();
|
||||
|
||||
SaveSlotInfo slot1 = slotManager.AllocateAutoSlot(sessionId);
|
||||
SaveSlotInfo slot2 = slotManager.AllocateAutoSlot(sessionId);
|
||||
SaveSlotInfo slot3 = slotManager.AllocateAutoSlot(sessionId);
|
||||
|
||||
// 4th should rotate to reuse the oldest
|
||||
SaveSlotInfo slot4 = slotManager.AllocateAutoSlot(sessionId);
|
||||
|
||||
// slot4 should reuse slot1's file path (oldest by timestamp)
|
||||
Assert.AreEqual(slot1.filePath, slot4.filePath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllocateQuickSlot_AlwaysReturnsSameSlot() {
|
||||
string sessionId = slotManager.CreateSession();
|
||||
|
||||
SaveSlotInfo slot1 = slotManager.AllocateQuickSlot(sessionId);
|
||||
SaveSlotInfo slot2 = slotManager.AllocateQuickSlot(sessionId);
|
||||
|
||||
Assert.AreEqual(slot1.filePath, slot2.filePath);
|
||||
Assert.AreEqual(SaveSlotType.Quick, slot1.slotType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSlots_ReturnsOnlySessionSlots() {
|
||||
string session1 = slotManager.CreateSession();
|
||||
string session2 = slotManager.CreateSession();
|
||||
|
||||
slotManager.AllocateManualSlot(session1);
|
||||
slotManager.AllocateManualSlot(session1);
|
||||
slotManager.AllocateManualSlot(session2);
|
||||
|
||||
IReadOnlyList<SaveSlotInfo> slots1 = slotManager.GetSlots(session1);
|
||||
IReadOnlyList<SaveSlotInfo> slots2 = slotManager.GetSlots(session2);
|
||||
|
||||
Assert.AreEqual(2, slots1.Count);
|
||||
Assert.AreEqual(1, slots2.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasAnySaves_FalseWhenEmpty_TrueAfterAllocation() {
|
||||
Assert.IsFalse(slotManager.HasAnySaves());
|
||||
|
||||
string sessionId = slotManager.CreateSession();
|
||||
slotManager.AllocateManualSlot(sessionId);
|
||||
|
||||
Assert.IsTrue(slotManager.HasAnySaves());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteSlot_RemovesFromIndex() {
|
||||
string sessionId = slotManager.CreateSession();
|
||||
SaveSlotInfo slot = slotManager.AllocateManualSlot(sessionId);
|
||||
|
||||
slotManager.DeleteSlot(slot);
|
||||
|
||||
Assert.AreEqual(0, slotManager.GetSlots(sessionId).Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteSession_RemovesAllSlotsAndSession() {
|
||||
string sessionId = slotManager.CreateSession();
|
||||
slotManager.AllocateManualSlot(sessionId);
|
||||
slotManager.AllocateAutoSlot(sessionId);
|
||||
slotManager.AllocateQuickSlot(sessionId);
|
||||
|
||||
slotManager.DeleteSession(sessionId);
|
||||
|
||||
Assert.AreEqual(0, slotManager.GetAllSessions().Count);
|
||||
Assert.AreEqual(0, slotManager.GetSlots(sessionId).Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In-memory ISaveStorage for testing without file system.
|
||||
/// </summary>
|
||||
private sealed class InMemorySaveStorage : ISaveStorage {
|
||||
private readonly Dictionary<string, byte[]> files = new Dictionary<string, byte[]>();
|
||||
private readonly HashSet<string> directories = new HashSet<string>();
|
||||
|
||||
public void Write(string path, byte[] data) { files[path] = data; }
|
||||
public byte[] Read(string path) { return files[path]; }
|
||||
public bool Exists(string path) { return files.ContainsKey(path); }
|
||||
public void Delete(string path) { files.Remove(path); }
|
||||
public string[] List(string directoryPath) {
|
||||
return files.Keys
|
||||
.Where(k => k.StartsWith(directoryPath))
|
||||
.ToArray();
|
||||
}
|
||||
public void CreateDirectory(string path) { directories.Add(path); }
|
||||
|
||||
public Task WriteAsync(string path, byte[] data) { Write(path, data); return Task.CompletedTask; }
|
||||
public Task<byte[]> ReadAsync(string path) { return Task.FromResult(Read(path)); }
|
||||
public Task<bool> ExistsAsync(string path) { return Task.FromResult(Exists(path)); }
|
||||
public Task DeleteAsync(string path) { Delete(path); return Task.CompletedTask; }
|
||||
public Task<string[]> ListAsync(string directoryPath) { return Task.FromResult(List(directoryPath)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Tests/Editor/SaveSlotManagerTests.cs.meta
Normal file
2
Tests/Editor/SaveSlotManagerTests.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 942e63ef3dd14ac4294a5330ba0442c4
|
||||
143
Tests/Editor/SaveSystemFacadeTests.cs
Normal file
143
Tests/Editor/SaveSystemFacadeTests.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Jovian.SaveSystem.Tests.Editor {
|
||||
public class SaveSystemFacadeTests {
|
||||
[Serializable]
|
||||
private sealed class GameState {
|
||||
public string playerName;
|
||||
public int level;
|
||||
public float health;
|
||||
}
|
||||
|
||||
private InMemorySaveStorage storage;
|
||||
private SaveSystemSettings settings;
|
||||
private ISaveSystem saveSystem;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {
|
||||
storage = new InMemorySaveStorage();
|
||||
settings = new SaveSystemSettings {
|
||||
maxAutoSavesPerSession = 3,
|
||||
currentSaveVersion = 1
|
||||
};
|
||||
JsonSaveSerializer serializer = new JsonSaveSerializer();
|
||||
SaveSlotManager slotManager = new SaveSlotManager(storage, settings);
|
||||
saveSystem = new SaveSystem(serializer, storage, slotManager, settings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SaveAndLoad_ManualSlot_RoundTrips() {
|
||||
string sessionId = saveSystem.CreateSession();
|
||||
GameState original = new GameState {
|
||||
playerName = "Hero",
|
||||
level = 10,
|
||||
health = 95.5f
|
||||
};
|
||||
|
||||
saveSystem.Save(sessionId, original, SaveSlotType.Manual);
|
||||
|
||||
IReadOnlyList<SaveSlotInfo> slots = saveSystem.GetSlots(sessionId);
|
||||
Assert.AreEqual(1, slots.Count);
|
||||
|
||||
GameState loaded = saveSystem.Load<GameState>(slots[0]);
|
||||
Assert.AreEqual(original.playerName, loaded.playerName);
|
||||
Assert.AreEqual(original.level, loaded.level);
|
||||
Assert.AreEqual(original.health, loaded.health);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SaveAndLoad_QuickSlot_OverwritesPrevious() {
|
||||
string sessionId = saveSystem.CreateSession();
|
||||
|
||||
saveSystem.Save(sessionId, new GameState { playerName = "First" }, SaveSlotType.Quick);
|
||||
saveSystem.Save(sessionId, new GameState { playerName = "Second" }, SaveSlotType.Quick);
|
||||
|
||||
IReadOnlyList<SaveSlotInfo> slots = saveSystem.GetSlots(sessionId);
|
||||
SaveSlotInfo quickSlot = slots.First(s => s.slotType == SaveSlotType.Quick);
|
||||
|
||||
GameState loaded = saveSystem.Load<GameState>(quickSlot);
|
||||
Assert.AreEqual("Second", loaded.playerName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasAnySaves_ReflectsState() {
|
||||
Assert.IsFalse(saveSystem.HasAnySaves());
|
||||
|
||||
string sessionId = saveSystem.CreateSession();
|
||||
saveSystem.Save(sessionId, new GameState { playerName = "Test" }, SaveSlotType.Manual);
|
||||
|
||||
Assert.IsTrue(saveSystem.HasAnySaves());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteSlot_RemovesSave() {
|
||||
string sessionId = saveSystem.CreateSession();
|
||||
saveSystem.Save(sessionId, new GameState { playerName = "Delete Me" }, SaveSlotType.Manual);
|
||||
|
||||
IReadOnlyList<SaveSlotInfo> slots = saveSystem.GetSlots(sessionId);
|
||||
saveSystem.DeleteSlot(slots[0]);
|
||||
|
||||
Assert.AreEqual(0, saveSystem.GetSlots(sessionId).Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteSession_RemovesEverything() {
|
||||
string sessionId = saveSystem.CreateSession();
|
||||
saveSystem.Save(sessionId, new GameState { playerName = "A" }, SaveSlotType.Manual);
|
||||
saveSystem.Save(sessionId, new GameState { playerName = "B" }, SaveSlotType.Auto);
|
||||
saveSystem.Save(sessionId, new GameState { playerName = "C" }, SaveSlotType.Quick);
|
||||
|
||||
saveSystem.DeleteSession(sessionId);
|
||||
|
||||
Assert.AreEqual(0, saveSystem.GetAllSessions().Count);
|
||||
Assert.IsFalse(saveSystem.HasAnySaves());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleSessions_AreIndependent() {
|
||||
string session1 = saveSystem.CreateSession();
|
||||
string session2 = saveSystem.CreateSession();
|
||||
|
||||
saveSystem.Save(session1, new GameState { playerName = "Player1" }, SaveSlotType.Manual);
|
||||
saveSystem.Save(session2, new GameState { playerName = "Player2" }, SaveSlotType.Manual);
|
||||
|
||||
Assert.AreEqual(1, saveSystem.GetSlots(session1).Count);
|
||||
Assert.AreEqual(1, saveSystem.GetSlots(session2).Count);
|
||||
|
||||
GameState loaded1 = saveSystem.Load<GameState>(saveSystem.GetSlots(session1)[0]);
|
||||
GameState loaded2 = saveSystem.Load<GameState>(saveSystem.GetSlots(session2)[0]);
|
||||
|
||||
Assert.AreEqual("Player1", loaded1.playerName);
|
||||
Assert.AreEqual("Player2", loaded2.playerName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In-memory ISaveStorage for testing.
|
||||
/// </summary>
|
||||
private sealed class InMemorySaveStorage : ISaveStorage {
|
||||
private readonly Dictionary<string, byte[]> files = new Dictionary<string, byte[]>();
|
||||
private readonly HashSet<string> directories = new HashSet<string>();
|
||||
|
||||
public void Write(string path, byte[] data) { files[path] = data; }
|
||||
public byte[] Read(string path) { return files[path]; }
|
||||
public bool Exists(string path) { return files.ContainsKey(path); }
|
||||
public void Delete(string path) { files.Remove(path); }
|
||||
public string[] List(string directoryPath) {
|
||||
return files.Keys
|
||||
.Where(k => k.StartsWith(directoryPath))
|
||||
.ToArray();
|
||||
}
|
||||
public void CreateDirectory(string path) { directories.Add(path); }
|
||||
|
||||
public Task WriteAsync(string path, byte[] data) { Write(path, data); return Task.CompletedTask; }
|
||||
public Task<byte[]> ReadAsync(string path) { return Task.FromResult(Read(path)); }
|
||||
public Task<bool> ExistsAsync(string path) { return Task.FromResult(Exists(path)); }
|
||||
public Task DeleteAsync(string path) { Delete(path); return Task.CompletedTask; }
|
||||
public Task<string[]> ListAsync(string directoryPath) { return Task.FromResult(List(directoryPath)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Tests/Editor/SaveSystemFacadeTests.cs.meta
Normal file
2
Tests/Editor/SaveSystemFacadeTests.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55a1496c116a3434291a828b258bbb97
|
||||
8
Tests/Runtime.meta
Normal file
8
Tests/Runtime.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b9f7ed9a26cede488cbe67e3bed5938
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
22
Tests/Runtime/Jovian.SaveSystem.RuntimeTests.asmdef
Normal file
22
Tests/Runtime/Jovian.SaveSystem.RuntimeTests.asmdef
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "Jovian.SaveSystem.RuntimeTests",
|
||||
"rootNamespace": "Jovian.SaveSystem.Tests.Runtime",
|
||||
"references": [
|
||||
"Jovian.SaveSystem",
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Tests/Runtime/Jovian.SaveSystem.RuntimeTests.asmdef.meta
Normal file
7
Tests/Runtime/Jovian.SaveSystem.RuntimeTests.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c0ac5542b5d3b846a1ed415880d1411
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user