- Home /
How can i save the games inventory?
I have an inventory code, i am need to know how can I save it, when I load back the game this is my inventory code
public delegate void OnItemChanged();
public OnItemChanged onItemChangeCallback;
public int space = 20;
public List<Item> items = new List<Item>();
public bool Add (Item item)
{
if (!item.isDefaultItem)
{
if (items.Count >= space)
{
Debug.Log("Not enough room.");
return false;
}
items.Add(item);
if (onItemChangeCallback != null)
onItemChangeCallback.Invoke();
}
return true;
}
public void Remove (Item item)
{
items.Remove(item);
if (onItemChangeCallback != null)
onItemChangeCallback.Invoke();
}
my slot code
public Image icon;
public Button removeButton;
Item item;
public void AddItem(Item newItem)
{
item = newItem;
icon.sprite = item.icon;
icon.enabled = true;
removeButton.interactable = true;
}
public void ClearSlot()
{
item = null;
icon.sprite = null;
icon.enabled = false;
removeButton.interactable = false;
}
public void OnRemoveButton()
{
Inventory.instance.Remove(item);
}
public void UseItem()
{
if (item != null)
{
item.Use();
}
}
and my inventory code
new public string name = "New Item";
public Sprite icon = null;
public bool isDefaultItem = false;
public virtual void Use()
{
//Use the item
//Something might happen
Debug.Log("Using " + name);
}
public void RemoveFromInventory ()
{
Inventory.instance.Remove(this);
}
please help!
Answer by exploringunity · May 14, 2020 at 07:05 PM
In general, .saving and loading data in Unity is no different than in other C# applications. You'll need:
A serializable class to hold the data you want to save -- anything
[System.Serializable]
A serializer/deserializer, such as .NET's
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
A stream to (de)serialize -- most likely a
FileStream
I'll provide a simple, but complete, example that demonstrates saving and loading a custom inventory class below. First, a preview:
To test, you'll need to add the Player
component to a GameObject in your scene, then enter play mode. Pressing 1
adds to the inventory, 2
removes a random item, 3
prints the inventory to the console, 4
saves the current inventory, and 5
loads the saved inventory.
An inventory is just a list of items -- this is what we'll be serializing as our save data.
Assets/Inventory.cs
using System.Collections.Generic;
[System.Serializable]
public class Inventory
{
public List<Item> items;
public Inventory() { items = new List<Item>(); }
}
An item has a few simple properties. Note that it also has the Serializable
attribute.
Assets/Item.cs
[System.Serializable] public class Item { public string description; public int value;
public Item(string description_, int value_)
{
description = description_;
value = value_;
}
public override string ToString() { return $"{description} -- {value}"; }
}
The player class holds the save/load logic, and some code to help test. The SaveInventory
and LoadInventory
functions are what's most important.
Assets/Player.cs
using System.IO;
using UnityEngine;
public class Player : MonoBehaviour
{
public Inventory inventory = new Inventory();
string InventorySavePath => Application.persistentDataPath + "/inventory.save";
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1)) { AddItemToInventory(); }
if (Input.GetKeyDown(KeyCode.Alpha2))
{
if (inventory.items.Count > 0) { RemoveItemFromInventory(); }
}
if (Input.GetKeyDown(KeyCode.Alpha3)) { DebugInventory(); }
if (Input.GetKeyDown(KeyCode.Alpha4)) { SaveInventory(); }
if (Input.GetKeyDown(KeyCode.Alpha5)) { LoadInventory(); }
}
void DebugInventory()
{
foreach (var item in inventory.items)
{
Debug.Log(item);
}
}
void AddItemToInventory()
{
var item = new Item(System.Guid.NewGuid().ToString(), Random.Range(1, 100));
Debug.Log($"Adding item: {item}");
inventory.items.Add(item);
}
void RemoveItemFromInventory()
{
var randomIdx = Random.Range(0, inventory.items.Count);
var item = inventory.items[randomIdx];
Debug.Log($"Removing item: {item}");
inventory.items.RemoveAt(randomIdx);
}
void SaveInventory()
{
Debug.Log($"Saving inventory to file @ {InventorySavePath}");
var stream = new FileStream(InventorySavePath, FileMode.Create, FileAccess.Write);
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formatter.Serialize(stream, inventory);
stream.Close();
}
void LoadInventory()
{
Debug.Log($"Loading inventory from file @ {InventorySavePath}");
if (File.Exists(InventorySavePath))
{
var stream = new FileStream(InventorySavePath, FileMode.Open, FileAccess.Read);
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
inventory = (Inventory)formatter.Deserialize(stream);
stream.Close();
}
else { Debug.LogError("Save file does not exist!"); }
}
}
Hope this helps!
i have scriptable objects as items, does that change anything?
Yes, and no :) You can't (well, probably shouldn't) serialize a ScriptableObject -- see the note at end of comment for details -- but even if you weren't not using ScriptableObjects, you probably don't want to copy the example above exactly. It's a bit naive in that it saves/loads every field of every item (imagine what the save file looks like it you have 999 identical health potions).
You probably want a single representation of your item -- which you already have in your [CreateAsset$$anonymous$$enu] class Item : ScriptableObject
. With that in place, you only need to save a list of item unique ids or names, or a list of (item id -> count) if you have a game where it's common to have several instances of a single item need to save space. When you load the data, you can look up the items by their unique id to repopulate the inventory.
With all that said, let's say you had a field in your Item ScriptableObject string uniqueId
, maybe with values like "$$anonymous$$or_health_potion". Then the Item and Inventory classes above could be renamed ItemSaveData and InventorySaveData. Also rename ItemSaveData's fields description
and value
to uniqueId
and count
. The last thing you'd need to do is convert Inventory to/from InventorySaveData in the save/load functions. I'll leave that as an exercise for the reader :)
Note: If you try to serialize a ScriptableObject using the method above, you'll get the following error: : SerializationException: Type UnityEngine.ScriptableObject in assembly UnityEngine.Core$$anonymous$$odule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is not marked as serializable.
There are way around this using other serialization methods -- in general, you can do some wizardly stuff with System.Reflection
-- but you should take this as a sign that another approach may be better.
Do you have a discord, if you do please give it to me, I want to chat to you about something, or is there another way to reach you tell me please.
Your answer
Follow this Question
Related Questions
I want to save my level progress in my quiz game 1 Answer
How to save and load inventory? 1 Answer
Save Game Sceenes user quit aplication, Can I save the scene as a whole while leaving the game? 0 Answers
How to make a list of saves and load them correctly 0 Answers
Persisting data between scenes: can't find an answer 2 Answers