One trick is to put your combat area in the same scene as your world, but organized under different empty GameObjects and positioned away from each other, such as:
-
World
-
World player avatar
-
World camera
-
World environment, etc.
-
Combat Area
-
Combat player avatar
-
Combat camera
-
Combat environment, etc.
When the player engages in combat, deactivate World and activate Combat Area. When the combat is done, deactivate Combat Area and activate World. If your world player avatar has components that track the player’s stats, you can copy those stats to the combat player avatar before combat and then copy them back after combat. This way you don’t have to worry about changing scenes.
If you don’t want to do that, you could generalize the persistence tutorial using something like this:
Create a static C# class that’s not a MonoBehaviour. For example:
SaveManager.cs
public static class SaveManager {
public delegate void SaveRestoreDelegate();
public static event SaveRestoreDelegate Save = delegate{};
public static event SaveRestoreDelegate Restore = delegate {};
}
You could pretty this up syntactically, and also actually test it (as I’m just typing it into this reply untested), but the idea is up there.
Then create a base save/restore component:
AbstractSave.cs
using UnityEngine;
public abstract class AbstractSave : MonoBehaviour {
public string playerPrefsKey; // assign unique value
protected abstract void OnSave();
protected abstract void OnRestore();
protected virtual void OnEnable() {
if (string.IsNullOrEmpty(playerPrefsKey)) playerPrefsKey = name;
SaveManager.Save += OnSave;
SaveManager.Restore += OnRestore;
}
protected virtual void OnDisable() {
SaveManager.Save -= OnSave;
SaveManager.Restore -= OnRestore;
}
}
And then write subclasses for different types of data:
SavePosition.cs
using UnityEngine;
public class SavePosition : AbstractSave {
protected override void OnSave() {
PlayerPrefs.SetFloat(playerPrefsKey + ".x", transform.position.x);
PlayerPrefs.SetFloat(playerPrefsKey + ".y", transform.position.y);
}
protected override void OnRestore() {
transform.position = new Vector3(
PlayerPrefs.GetFloat(playerPrefsKey + ".x", transform.position.x),
PlayerPrefs.GetFloat(playerPrefsKey + ".y", transform.position.y),
transform.position.z);
}
}
If you add SavePosition to a GameObject, it will save and restore its (x,y) position.
Finally, before changing scenes, call SaveManager.Save(). After changing scenes, call SaveManager.Restore(). For example, to switch to the Combat scene:
SaveManager.Save();
SceneManager.LoadScene("Combat");
SaveManager.Restore();
When combat is over, switch back to the World scene:
SaveManager.Save();
SceneManager.LoadScene("World");
SaveManager.Restore();