Suggestion for saving an entire scene?

Discussion and help for Easy Save 3
vectorxstudios
Posts: 16
Joined: Fri Jun 08, 2018 6:06 pm

Suggestion for saving an entire scene?

Post by vectorxstudios »

I have a game with multiple zones + a base zone that never changes.

My game is a survival type and I have hundreds or thousands of instantiated objects depending on how long the player has been in a particular scene.

Do you have a suggestion on how I could save the entire scene, or at least every object tagged with a component? I have everything from AI state machines to item fields and more.

I would like to load in static zone objects via Unity and then load in everything else via ES3.

Thoughts?
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Suggestion for saving an entire scene?

Post by Joel »

Hi there,

If you have thousands of objects then I would not recommend saving every GameObject in it's entirety, as this would be extremely performance intensive and much of the GameObject probably does not need saving.

Instead I would first create a UniqueID script which creates a unique identifier for each of your types of prefab. For example, you could attach the script below to your prefabs to do this (not to the prefab instance):
using UnityEngine;

public class UniqueID : MonoBehaviour 
{
	public string guid = System.Guid.NewGuid().ToString();
}
I would then create a script which contains all of the UniqueIDs of the prefabs you are going to instantiate. Let's call this the PrefabManager.

In this script we will also create a List<UniqueID> which will contain all of the UniqueIDs of the objects we instantiate. Whenever you instantiate one of your prefabs, add the UniqueID of it's prefab to this list. You could add an InstantiatePrefab method which you call instead of Unity's Instantiate method. This would look something like:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PrefabManager : MonoBehaviour 
{
	public UniqueID[] prefabs;
	private List<UniqueID> prefabInstances = new List<UniqueID>();

	public GameObject InstantiatePrefab(GameObject prefab)
	{
		var go = Instantiate(prefab);
		prefabInstances.Add(go.GetComponent<UniqueID>());
		return go;
	}
}
To this script we can then add a Save() method, which we can call whenever we want to save. This method will create an array containing the guid's of all of the prefabs we've instantiated, and an array of all of their Transforms. We then save these arrays. This method would look something like:
public void Save() 
{
	string[] guids = new string[prefabInstances.Count];
	Transform[] transforms = new Transform[prefabInstances.Count];
	for(int i = 0; i < guids.Length; i++)
	{
		guids  = prefabInstances .guid;
		transforms  = prefabInstances .transform;
	}
	ES3.Save<string[]>("guids", guids);
	ES3.Save<Transform[]>("transforms", transforms);
}


We would then need to add a Load() method, which loads the guids, and then instantiates the prefab with each given guid. We should also create an array of the Transforms we've instantiated, so we can then use ES3.LoadInto to load the Transforms into the new instances. This would look something like:

public void Load()
{
	prefabInstances = new List<UniqueID> ();
	string[] guids = ES3.Load<string[]>("guids");
	List<Transform> transforms = new List<Transform>();

	foreach (var guid in guids)
	{
		// Find the prefab with this GUID.
		foreach(var prefab in prefabs)
		{
			if(prefab.guid == guid)
			{
				transforms.Add();

				var go = InstantiatePrefab(prefab.gameObject);
				transforms.Add(go.transform);
			}
		}
	}
	ES3.LoadInto("transforms", transforms);
}


Note that you could also save other Components on the GameObject, not just the Transform, by creating additional arrays. You can find information on what Components can be saved, and how to add support for other Components here: https://docs.moodkie.com/easy-save-3/es ... ted-types/

The complete script would look something like this, though this is only provided as an example and you may need to modify it for your own purposes:

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

public class PrefabManager : MonoBehaviour 
{
	public UniqueID[] prefabs;
	private List<UniqueID> prefabInstances = new List<UniqueID>();

	public GameObject InstantiatePrefab(GameObject prefab)
	{
		var go = Instantiate(prefab);
		prefabInstances.Add(go.GetComponent<UniqueID>());
		return go;
	}

	public void Save() 
	{
		string[] guids = new string[prefabInstances.Count];
		Transform[] transforms = new Transform[prefabInstances.Count];
		for(int i = 0; i < guids.Length; i++)
		{
			guids  = prefabInstances .guid;
			transforms  = prefabInstances .transform;
		}
		ES3.Save<string[]>("guids", guids);
		ES3.Save<Transform[]>("transforms", transforms);
	}

	public void Load()
	{
		prefabInstances = new List<UniqueID> ();
		string[] guids = ES3.Load<string[]>("guids");
		List<Transform> transforms = new List<Transform>();

		foreach (var guid in guids)
		{
			// Find the prefab with this GUID.
			foreach(var prefab in prefabs)
				if(prefab.guid == guid)
				{
						var go = InstantiatePrefab(prefab.gameObject).GetComponent<UniqueID>();
						transforms.Add(go.transform);
				}
		}
		ES3.LoadInto("transforms", transforms);
	}
}


All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
vectorxstudios
Posts: 16
Joined: Fri Jun 08, 2018 6:06 pm

Re: Suggestion for saving an entire scene?

Post by vectorxstudios »

Thanks Joel!

I'll try this once I can figure out why my types are not showing up in the Types search list...
vectorxstudios
Posts: 16
Joined: Fri Jun 08, 2018 6:06 pm

Re: Suggestion for saving an entire scene?

Post by vectorxstudios »

Question on your description:

Does this only work for one game object type? For example, Trees and not Animals (which have different components)?

And is your InstantiatePrefab a ES function or just a placeholder you put for me to instantiate my game object?

Thanks!
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Suggestion for saving an entire scene?

Post by Joel »

Hi there,

This would indeed only work on one GameObject type. An alternative would be to have multiple managers for each GameObject type.

Or another alternative would be to modify the ES3Type for GameObject so that it only saves the Components you tell it to. For example, you could attach a Component to your prefab which contains an array containing the Components you want to save. This could then be used to tell the ES3Type which Components you want to save.

I've created a modified version of the ES3Type and PM'd it to you. After importing, you will need to attach a ComponentsToSave component to your prefabs, and drag the Components you wish to save into it's components array. You can then use the instructions here to save your prefab instances. Note that in your case, you will probably want to save an array of GameObjects, instead of saving each GameObject individually.

Also just to clarify, in the previous example the InstantiatePrefab function is not part of the Easy Save API, and is declared in the example.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
vectorxstudios
Posts: 16
Joined: Fri Jun 08, 2018 6:06 pm

Re: Suggestion for saving an entire scene?

Post by vectorxstudios »

Oh wow!!! Thanks for the help and great customer service. Easy Save just got another 5-star review.. :)
vectorxstudios
Posts: 16
Joined: Fri Jun 08, 2018 6:06 pm

Re: Suggestion for saving an entire scene?

Post by vectorxstudios »

Joel wrote:Hi there,

This would indeed only work on one GameObject type. An alternative would be to have multiple managers for each GameObject type.

Or another alternative would be to modify the ES3Type for GameObject so that it only saves the Components you tell it to. For example, you could attach a Component to your prefab which contains an array containing the Components you want to save. This could then be used to tell the ES3Type which Components you want to save.

I've created a modified version of the ES3Type and PM'd it to you. After importing, you will need to attach a ComponentsToSave component to your prefabs, and drag the Components you wish to save into it's components array. You can then use the instructions here to save your prefab instances. Note that in your case, you will probably want to save an array of GameObjects, instead of saving each GameObject individually.

Also just to clarify, in the previous example the InstantiatePrefab function is not part of the Easy Save API, and is declared in the example.

All the best,
Joel
ComponentsToSave is not a component that shows up? The asset only had a ES3_Type for game object in it.
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Suggestion for saving an entire scene?

Post by Joel »

Thanks for the great review, it's much appreciated!

Regarding the ComponentsToSave class, I put it at the bottom of the ES3Type_GameObject script but it looks like Easy Save doesn't like this. I've PM'd you a new package with the ComponentsToSave class in a separate script.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
WadeSacca
Posts: 4
Joined: Thu Jun 21, 2018 4:50 pm

Re: Suggestion for saving an entire scene?

Post by WadeSacca »

This is exactly the solution I have spent the last two days looking for. I already owned Easy Save but for some reason had not considered using it. However, I have encountered some issues with the code you posted in the Load function. The Instantiate and save functions appear to work perfectly.

In the Load there are 2 issues that I see.

The first is with the prefabinstances.add line. You are adding to the list but you are also calling the prefab function which also adds to the list so it is adding it twice. Unless I am missing something, this line should read:

Code: Select all

InstantiatePrefab (prefab.gameObject);
The second issue and the one that has me completely stumped is with the loadinto line. I just don't understand what it is trying to do. It is throwing a null exception error. I tried to read the documentation but your line of code does not even match the documentation and any modification I make to it does not seem to be clearing the error. Since I don't understand what it is trying to do, I can't seem to fix it. At the top you create an array to hold the transforms but never load anything into it at the beginning. Then after the for loops are completed, you call this loadinto function. How does it know what GO it is supposed to be loading the transform into without a reference to that GO or something?

Sorry for my ignorance but I just don't understand what is going wrong and I am so close to what I have searched for days to accomplish.
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Suggestion for saving an entire scene?

Post by Joel »

Hi there,

You are indeed correct regarding the InstantiatePrefab call.

And regarding the LoadInto call, it looks like I forgot to assign the Transforms to the array in the for loop. This was only meant as a vague example and not supposed to work out of the box, but I've modified it in the original post to represent this incase anyone decides to use this code as is.

Note that LoadInto loads the Transforms from file directly into the Transforms in the transforms List, rather than creating new instances.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Post Reply