{"id":29859206,"url":"https://github.com/pietras333/save-load-system","last_synced_at":"2025-07-30T02:11:32.346Z","repository":{"id":304348579,"uuid":"1018528285","full_name":"pietras333/save-load-system","owner":"pietras333","description":"A comprehensive, modular save/load system for Unity games with support for multiple save slots, automatic screenshots, and flexible data management - similar to Minecraft's world system.","archived":false,"fork":false,"pushed_at":"2025-07-12T13:08:55.000Z","size":21,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-12T15:23:36.271Z","etag":null,"topics":["game-development","json","save-load","unity3d"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pietras333.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-12T13:04:21.000Z","updated_at":"2025-07-12T13:10:27.000Z","dependencies_parsed_at":"2025-07-12T15:23:39.752Z","dependency_job_id":"51fbd632-c4aa-4178-b239-fe8d347df9f5","html_url":"https://github.com/pietras333/save-load-system","commit_stats":null,"previous_names":["pietras333/save-load-system"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/pietras333/save-load-system","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietras333%2Fsave-load-system","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietras333%2Fsave-load-system/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietras333%2Fsave-load-system/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietras333%2Fsave-load-system/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pietras333","download_url":"https://codeload.github.com/pietras333/save-load-system/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietras333%2Fsave-load-system/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267797672,"owners_count":24145709,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["game-development","json","save-load","unity3d"],"created_at":"2025-07-30T02:11:29.844Z","updated_at":"2025-07-30T02:11:32.292Z","avatar_url":"https://github.com/pietras333.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unity Multi-Save System\n\nA comprehensive, modular save/load system for Unity games with support for multiple save slots, automatic screenshots, and flexible data management - similar to Minecraft's world system.\n\n## Features\n\n### Core Functionality\n- **Multiple Save Slots**: Create, load, delete, and duplicate game saves\n- **Automatic Screenshots**: Capture and display save thumbnails\n- **Flexible Data Structure**: Modular data packs for different game systems\n- **Async Operations**: Non-blocking save/load operations\n- **Metadata Management**: Rich save information with play time, timestamps, and custom data\n- **Error Handling**: Robust error handling with fallback to defaults\n\n### Advanced Features\n- **Priority-Based Loading**: Load data packs in specific order\n- **Selective Saving**: Save individual data packs or all at once\n- **Data Validation**: Version compatibility checking\n- **Auto-Save**: Automatic saving on application pause/focus loss\n- **Memory Management**: Efficient resource cleanup\n\n## Quick Start\n\n### 1. Installation\n\nCopy all the provided scripts into your Unity project:\n- `MultiSaveManager.cs`\n- `SaveLoadUI.cs`\n- `EnhancedSaveManager.cs`\n- Core interfaces and classes\n\n### 2. Basic Setup\n\n```csharp\n// Create your data structures\n[Serializable]\npublic class PlayerData\n{\n    public int Level = 1;\n    public int Experience = 0;\n    public int Gold = 100;\n    public Vector3 Position = Vector3.zero;\n}\n\n// Create data packs\npublic class PlayerDataPack : DataPack\u003cPlayerData\u003e\n{\n    public override string FileName =\u003e \"player.json\";\n    public override int Priority =\u003e 1; // Load first\n}\n```\n\n### 3. Scene Setup\n\n1. Create an empty GameObject and attach `MultiSaveManager` script\n2. Set up your UI with the provided `SaveLoadUI` script\n3. Configure screenshot settings if using `EnhancedSaveManager`\n\n### 4. Basic Usage\n\n```csharp\npublic class GameManager : MonoBehaviour\n{\n    private MultiSaveManager saveManager;\n    \n    void Start()\n    {\n        saveManager = FindObjectOfType\u003cMultiSaveManager\u003e();\n        \n        // Create a new save\n        await saveManager.CreateNewSave(\"My Adventure\", \"Starting my journey!\");\n        \n        // Load an existing save\n        await saveManager.LoadGameById(\"20240712_143022_1234\");\n        \n        // Access data\n        var playerData = saveManager.PlayerData;\n        playerData.Level = 5;\n        \n        // Save changes\n        await saveManager.SaveCurrentGame();\n    }\n}\n```\n\n## Architecture Overview\n\n### Core Components\n\n```\nMultiSaveManager\n├── IDataOperationService (DataOperationService)\n├── IDataService (FileDataService)\n├── IDataPack (PlayerDataPack, WorldDataPack, etc.)\n└── GameSaveInfo (Metadata management)\n```\n\n### Data Flow\n\n1. **Save Creation**: Generate unique ID → Create directory → Initialize data packs\n2. **Data Loading**: Load metadata → Initialize data service → Load data packs by priority\n3. **Data Saving**: Update metadata → Save data packs → Capture screenshot\n4. **Save Management**: List saves → Handle duplicates → Delete saves\n\n## Data Structure\n\n### Save Directory Structure\n```\nMyGameSaves/\n├── 20240712_143022_1234/\n│   ├── metadata.json\n│   ├── screenshot.jpg\n│   ├── player.json\n│   ├── world.json\n│   └── settings.json\n├── 20240712_150045_5678/\n│   ├── metadata.json\n│   ├── screenshot.jpg\n│   └── ...\n```\n\n### Metadata Format\n```json\n{\n  \"SaveId\": \"20240712_143022_1234\",\n  \"SaveName\": \"My Adventure\",\n  \"Description\": \"Starting my journey!\",\n  \"CreatedDate\": \"2024-07-12T14:30:22.123Z\",\n  \"LastPlayedDate\": \"2024-07-12T15:45:30.456Z\",\n  \"PlayTime\": \"01:15:08\",\n  \"Version\": \"1.0.0\",\n  \"CustomMetadata\": {\n    \"PlayerLevel\": 5,\n    \"QuestsCompleted\": 3,\n    \"CurrentScene\": \"Forest_Level_1\"\n  }\n}\n```\n\n## Creating Custom Data Packs\n\n### 1. Define Your Data Structure\n\n```csharp\n[Serializable]\npublic class InventoryData\n{\n    public List\u003cItemData\u003e Items = new List\u003cItemData\u003e();\n    public int MaxSlots = 20;\n    public Dictionary\u003cstring, int\u003e ItemCounts = new Dictionary\u003cstring, int\u003e();\n}\n```\n\n### 2. Create the Data Pack\n\n```csharp\npublic class InventoryDataPack : DataPack\u003cInventoryData\u003e\n{\n    public override string FileName =\u003e \"inventory.json\";\n    public override int Priority =\u003e 2; // Load after player data\n    \n    protected override void OnDataLoaded()\n    {\n        // Custom logic after loading\n        Debug.Log($\"Loaded {Data.Items.Count} items\");\n    }\n    \n    protected override void OnDataReset()\n    {\n        // Custom logic when resetting to defaults\n        Data.Items.Clear();\n        Data.ItemCounts.Clear();\n    }\n}\n```\n\n### 3. Register in DataOperationService\n\n```csharp\npublic class DataOperationService : IDataOperationService\n{\n    public DataOperationService(IDataService dataService)\n    {\n        // ... existing code ...\n        \n        // Register your new data pack\n        RegisterDataPack(new InventoryDataPack());\n    }\n}\n```\n\n## UI Integration\n\n### Save/Load UI Setup\n\n1. Create a Canvas with the following structure:\n```\nCanvas\n├── SaveLoadPanel\n│   ├── SaveSlotContainer (Vertical Layout Group)\n│   ├── CreateNewSaveButton\n│   └── ClosePanelButton\n├── NewSaveDialog\n│   ├── SaveNameInput\n│   ├── SaveDescriptionInput\n│   ├── ConfirmCreateButton\n│   └── CancelCreateButton\n└── DeleteConfirmDialog\n    ├── ConfirmDeleteButton\n    └── CancelDeleteButton\n```\n\n2. Create a SaveSlot prefab with:\n```\nSaveSlotPrefab\n├── SaveNameText\n├── SaveDescriptionText\n├── LastPlayedText\n├── PlayTimeText\n├── ScreenshotImage\n├── LoadButton\n├── DeleteButton\n├── DuplicateButton\n└── CurrentSaveIndicator\n```\n\n### Accessing Save Data in UI\n\n```csharp\npublic class PlayerUI : MonoBehaviour\n{\n    private MultiSaveManager saveManager;\n    \n    void Start()\n    {\n        saveManager = FindObjectOfType\u003cMultiSaveManager\u003e();\n        \n        // Subscribe to save events\n        saveManager.OnSaveLoaded += OnSaveLoaded;\n        UpdatePlayerInfo();\n    }\n    \n    private void OnSaveLoaded(GameSaveInfo saveInfo)\n    {\n        UpdatePlayerInfo();\n    }\n    \n    private void UpdatePlayerInfo()\n    {\n        var playerData = saveManager.PlayerData;\n        if (playerData != null)\n        {\n            // Update UI elements\n            levelText.text = $\"Level: {playerData.Level}\";\n            goldText.text = $\"Gold: {playerData.Gold}\";\n        }\n    }\n}\n```\n\n## Advanced Features\n\n### Screenshot System\n\n```csharp\npublic class ScreenshotManager : MonoBehaviour\n{\n    [SerializeField] private Camera screenshotCamera;\n    [SerializeField] private Image saveSlotImage;\n    \n    public void DisplaySaveScreenshot(string saveId)\n    {\n        var saveManager = FindObjectOfType\u003cEnhancedSaveManager\u003e();\n        Texture2D screenshot = saveManager.GetSaveScreenshot(saveId);\n        \n        if (screenshot != null)\n        {\n            Sprite sprite = Sprite.Create(screenshot, \n                new Rect(0, 0, screenshot.width, screenshot.height), \n                Vector2.one * 0.5f);\n            saveSlotImage.sprite = sprite;\n        }\n    }\n}\n```\n\n### Custom Metadata\n\n```csharp\npublic class GameProgressTracker : MonoBehaviour\n{\n    private MultiSaveManager saveManager;\n    \n    void Start()\n    {\n        saveManager = FindObjectOfType\u003cMultiSaveManager\u003e();\n    }\n    \n    public void TrackBossDefeated(string bossName)\n    {\n        // Add custom metadata\n        saveManager.AddCustomMetadata($\"Boss_{bossName}_Defeated\", true);\n        saveManager.AddCustomMetadata($\"Boss_{bossName}_DefeatTime\", DateTime.Now);\n        \n        // Save immediately\n        saveManager.SaveCurrentGame();\n    }\n    \n    public bool IsBossDefeated(string bossName)\n    {\n        return saveManager.GetCustomMetadata\u003cbool\u003e($\"Boss_{bossName}_Defeated\");\n    }\n}\n```\n\n### Save Validation\n\n```csharp\npublic class SaveValidator : MonoBehaviour\n{\n    public bool ValidateSave(GameSaveInfo saveInfo)\n    {\n        // Check version compatibility\n        if (saveInfo.CustomMetadata.ContainsKey(\"GameVersion\"))\n        {\n            string saveVersion = saveInfo.CustomMetadata[\"GameVersion\"].ToString();\n            if (!IsVersionCompatible(saveVersion))\n            {\n                Debug.LogWarning($\"Save version {saveVersion} may not be compatible\");\n                return false;\n            }\n        }\n        \n        // Check required data\n        if (!saveInfo.CustomMetadata.ContainsKey(\"PlayerLevel\"))\n        {\n            Debug.LogError(\"Save missing required player data\");\n            return false;\n        }\n        \n        return true;\n    }\n    \n    private bool IsVersionCompatible(string saveVersion)\n    {\n        // Implement your version compatibility logic\n        Version save = new Version(saveVersion);\n        Version current = new Version(Application.version);\n        \n        return save.Major == current.Major;\n    }\n}\n```\n\n## Best Practices\n\n### Performance Optimization\n\n1. **Use Async Operations**: Always prefer async save/load operations\n2. **Batch Operations**: Group multiple save operations together\n3. **Lazy Loading**: Only load data when needed\n4. **Memory Management**: Properly dispose of resources\n\n```csharp\n// Good - Async operation\nawait saveManager.SaveGameAsync();\n\n// Good - Batch save specific packs\nsaveManager.Save\u003cPlayerDataPack\u003e();\nsaveManager.Save\u003cWorldDataPack\u003e();\n\n// Avoid - Synchronous operations in main thread\nsaveManager.SaveCurrentGameSync(); // Only use in OnApplicationPause\n```\n\n### Error Handling\n\n```csharp\npublic async Task\u003cbool\u003e SafeLoadSave(string saveId)\n{\n    try\n    {\n        return await saveManager.LoadGameById(saveId);\n    }\n    catch (Exception ex)\n    {\n        Debug.LogError($\"Failed to load save {saveId}: {ex.Message}\");\n        \n        // Fallback to default data\n        saveManager.Reset\u003cPlayerDataPack\u003e();\n        return false;\n    }\n}\n```\n\n### Data Migration\n\n```csharp\npublic class SaveMigrator : MonoBehaviour\n{\n    public void MigrateSave(GameSaveInfo saveInfo)\n    {\n        if (saveInfo.CustomMetadata.ContainsKey(\"DataVersion\"))\n        {\n            int version = (int)saveInfo.CustomMetadata[\"DataVersion\"];\n            \n            if (version \u003c 2)\n            {\n                // Migrate from version 1 to 2\n                MigrateFromV1ToV2(saveInfo);\n            }\n        }\n    }\n    \n    private void MigrateFromV1ToV2(GameSaveInfo saveInfo)\n    {\n        // Implement migration logic\n        saveInfo.CustomMetadata[\"DataVersion\"] = 2;\n    }\n}\n```\n\n## Requirements\n\n- Unity 2020.3 or later\n- Newtonsoft.Json (com.unity.nuget.newtonsoft-json)\n- TextMeshPro (com.unity.textmeshpro)\n\n## Dependencies\n\n```json\n{\n  \"dependencies\": {\n    \"com.unity.nuget.newtonsoft-json\": \"3.0.2\",\n    \"com.unity.textmeshpro\": \"3.0.6\"\n  }\n}\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Changelog\n\n### v1.0.0\n- Initial release\n- Multi-save system with UI\n- Screenshot support\n- Metadata management\n- Async operations\n- Error handling and validation\n\n---\n\n**Made with ❤️ for Unity developers**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpietras333%2Fsave-load-system","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpietras333%2Fsave-load-system","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpietras333%2Fsave-load-system/lists"}