Saving and Loading Dynamic Scenes

Hi, I am developing a hobby farm game where a player is able to place crops and grow them and build up a farm etc. I am having difficulties in saving and then loading the GameObjects the player creates.

Right now parts of my approach to it is quite hacky. Each GameObject (Crop) being spawned has a Crop class, which stores a CropData ScriptableObject which stores all of it’s data. So far I have the saving of the objects position and loading that back in working fine. However, I’m unsure how to figure out how to save the ScriptableObject the GameObject references.

Currently I am using a String Reference and loading the ScriptableObject in from the Resources folder (Code Below). This seems very hacky however I can’t think of other ways to do it.

//Saving The Objects Data

    private void OnDisable()
    {
        List<Transform> placedObjects = transform.GetComponentsInChildren<Transform>().ToList();
        placedObjects.Remove(transform);
       
        LevelData data = new LevelData();
       
        foreach(Transform t in placedObjects)
        {
            if(t.GetComponent<BaseCrop>())
            {
                CropData cropData = new CropData();
                cropData.transformData = new TransformData(t.localPosition.x, t.localPosition.y);
                cropData.itemScriptableObject = t.GetComponent<BaseCrop>().CropData.fileName;
               
                data.cropData.Add(cropData);
            }
        }

        SaveSystem<LevelData>.SaveData(data, "LevelData");
    }

//Data Class

using System;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class LevelData
{
    public List<CropData> cropData = new List<CropData>();
}

[Serializable]
public class CropData
{
    public TransformData transformData = new TransformData(0,0);
    public string itemScriptableObject = "";

}

[Serializable]
public class TransformData
{
    public TransformData(float _x, float _y)
    {
        x = _x;
        y = _y;
    }

    public float x;
    public float y;
}

//Loading Data in

    private void OnEnable()
    {
        LevelData data = SaveSystem<LevelData>.LoadData("LevelData");
        if(data == null)
        {
            Debug.Log("Not found");
        }
        else
        {

            //Loop through for all Placeable Object Types, Crops and Buildings so far
            foreach(CropData cropData in data.cropData)
            {
                Crop crop = (Crop)Resources.Load("Crops/" + cropData.itemScriptableObject);
                Vector2 spawnLocation = new Vector2(cropData.transformData.x, cropData.transformData.y);


                SpawnItem(crop, spawnLocation, Quaternion.identity);
            }
        }
    }

Scriptable objects in general are great for storing pre-set data, such as tuning variables that define your game or level.

For serializing/deserializing generic save games, there are a bunch of great tutorials online to guide you in the general direction, but usually you do NOT use Scriptable Objects for that. I’m not saying you can’t use them, but it’s generally not what they are for.

Instead I recommend using something like JSON to serialize the information you want to save and write it to a disk file, or if it is small, store it in PlayerPrefs.

Check this guy out:

He really knows his stuff; I’ve watched a ton of his videos. His material is very dense, so don’t be afraid to watch it a few times. It’s good stuff.

Thanks for the video link I had actually watched it before and wrote the base SaveSystem around that tutorial. The scriptable objects are only used to store generic data about the game items such as the cost, size etc. sorry if that wasn’t clear.

Would you recommend storing that in JSON and then loading that data in when the game loads up? I’m struggling to find a clean way to save what type the object is when I’m storing it and how to load that generic data back in. Because that generic data stores things like Sprites I’m not sure how to properly load that in. Would JSON make that easier?

Got it to work by basically redoing everything. For anyone who has this same problem this is what I did:

Created a folder with all my scriptable objects with all the data for my items in them.
Created prefabs for each item and assigned it a SO
When saving the game I looped through all placed items, got their ID’s and saved that into a JSON file
When loading the game back up I created a dictionary containing every items ID and the GO attatched to it. ( Got this data by looping through all the SO’s in the Resources folder)
Used that data to Instantiate all the objects in their previous locations