Redirect to the Docs main page.Docs

Save System NEW

Understanding the Save System

Learn how to use the save system in Ultimate Grid Inventory to persist inventory data between game sessions.

What is the Save System?

The Save System in Ultimate Grid Inventory (UGI) provides a flexible and extensible way to persist inventory data between game sessions. It allows you to:

  • Save and load player inventories
  • Persist container contents (backpacks, chests, etc.)
  • Store equipped items in holders
  • Maintain item metadata (stacks, durability, etc.)
  • Create custom save strategies for different storage methods

Save System Architecture

The UGI save system consists of several key components that work together:

Core Components

  1. SaveStrategySo: An abstract ScriptableObject that defines the interface for saving and loading data
  2. LocalSaveStrategySo: A concrete implementation that saves data to local files
  3. JsonInventoryUtility: A utility class that handles serialization and deserialization of inventory data
  4. InventorySo: The main inventory class that integrates with the save system

How It Works

The save system follows this general flow:

  1. Serialization: When saving, inventory items are converted to JSON using Newtonsoft.Json
  2. Storage: The serialized data is stored using the configured save strategy
  3. Retrieval: When loading, the serialized data is retrieved using the save strategy
  4. Deserialization: The JSON data is converted back to inventory items
  5. Reconstruction: The inventory state is reconstructed by re-equipping items to their holders

Basic Usage

Setting Up the Save System

To use the save system, you need to configure your InventorySo with a save strategy:

  1. Create a save strategy ScriptableObject:

    • Right-click in your Project window
    • Select Create > Inventory > Configuration > Save > Local Save Strategy
  2. Configure your InventorySo:

    • Select your inventory ScriptableObject
    • Assign the save strategy to the Save Strategy SO field
    • Ensure the Saveable checkbox is enabled

[//]: Inventory Save SettingsLoading image

Saving and Loading Inventory

To save and load inventory data in your game:

using Inventory.Scripts.Core.ScriptableObjects;
using UnityEngine;
 
public class InventorySaveManager : MonoBehaviour
{
    [SerializeField] private InventorySo playerInventory;
    
    // Save the inventory (e.g., when exiting the game)
    public void SaveInventory()
    {
        playerInventory.Save();
        Debug.Log("Inventory saved successfully!");
    }
    
    // Load the inventory (e.g., when starting the game)
    public void LoadInventory()
    {
        bool success = playerInventory.Load();
        Debug.Log(success ? "Inventory loaded successfully!" : "No saved inventory found.");
    }
}

Auto-Saving

You can implement auto-saving at key moments in your game:

// Auto-save when the player picks up an item
public void OnItemPickedUp(ItemTable item)
{
    // Add item to inventory...
    
    // Auto-save after important changes
    playerInventory.Save();
}

Creating Custom Save Strategies

The default LocalSaveStrategySo saves data to local files, but you can create custom save strategies for different storage methods (cloud saves, databases, etc.).

Creating a Custom Save Strategy

To create a custom save strategy:

  1. Create a new class that inherits from SaveStrategySo
  2. Implement the Save and Load methods
  3. Add a CreateAssetMenu attribute to make it available in the Unity menu

Here's an example of a custom save strategy that uses PlayerPrefs:

using Inventory.Scripts.Core.Controllers.Save;
using UnityEngine;
 
[CreateAssetMenu(menuName = "Inventory/Configuration/Save/PlayerPrefs Save Strategy")]
public class PlayerPrefsSaveStrategySo : SaveStrategySo
{
    public override void Save(string key, string jsonEquippedItems)
    {
        PlayerPrefs.SetString($"UGI_{key}", jsonEquippedItems);
        PlayerPrefs.Save();
        Debug.Log($"Saved inventory data to PlayerPrefs with key: UGI_{key}");
    }
 
    public override string Load(string key)
    {
        string fullKey = $"UGI_{key}";
        
        if (PlayerPrefs.HasKey(fullKey))
        {
            return PlayerPrefs.GetString(fullKey);
        }
        
        Debug.LogWarning($"No save data found in PlayerPrefs with key: {fullKey}");
        return null;
    }
}

Advanced Usage

Saving Environment Containers

To save containers in the game world (chests, lockers, etc.):

using Inventory.Scripts.Core.Environment;
using Inventory.Scripts.Core.ScriptableObjects;
using UnityEngine;
 
public class EnvironmentContainerManager : MonoBehaviour
{
    [SerializeField] private InventorySo environmentContainersSo;
    [SerializeField] private EnvironmentContainerHolder[] containerHolders;
    
    private void Start()
    {
        // Register all containers with the inventory
        foreach (var container in containerHolders)
        {
            environmentContainersSo.AddHolder(container.GetHolderData());
        }
        
        // Load saved container contents
        environmentContainersSo.Load();
    }
    
    private void OnDestroy()
    {
        // Save container contents before scene unload
        environmentContainersSo.Save();
    }
}

Working with Metadata

The save system automatically handles item metadata like stacks and container contents. For example, to access container contents after loading:

using Inventory.Scripts.Core.Items;
using Inventory.Scripts.Core.Items.Metadata;
using UnityEngine;
 
public class ContainerContentExample : MonoBehaviour
{
    public void DisplayContainerContents(ItemTable containerItem)
    {
        if (!containerItem.IsContainer()) return;
        
        var containerMetadata = containerItem.GetMetadata<ContainerMetadata>();
        if (containerMetadata == null) return;
        
        // Get all items from the container (including nested containers)
        var allItems = containerMetadata.GetAllItems(true);
        
        Debug.Log($"Container {containerItem.ItemDataSo.DisplayName} contains {allItems.Count} items:");
        foreach (var item in allItems)
        {
            Debug.Log($"- {item.ItemDataSo.DisplayName}");
        }
    }
}

Best Practices

  1. Save at Key Moments: Save after important changes to the inventory (adding/removing items, equipping/unequipping)
  2. Separate Inventories: Use separate InventorySo instances for different types of inventories (player, environment containers, etc.)
  3. Error Handling: Always check the return value of Load() to handle cases where no save data exists
  4. Testing: Test your save system thoroughly with different scenarios (empty inventory, full inventory, nested containers)
  5. Backup: Consider implementing a backup system for important save data

Next Steps

Now that you understand the save system, you can:

  • Implement different ways saving and loading in your game
  • Create custom save strategies for your specific needs
  • Integrate the save system with your game's UI
  • Add save/load functionality to your game's menu system

By leveraging the UGI save system, you can provide a seamless experience for players, ensuring their inventory progress is preserved between game sessions.

On this page