Restoring a previous state
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Restoring a previous state
Hi,
With the save system, is it possible to restore to a previos state without loading?
What I wont is to restore the state of all my objects to a state that I already saved reaching a node on the quest.
For instance on my game if the player dies, it destroys, but I don't load the scene again (its an open world and it takes a while to load it), so I'd like to call the save system and "load" the previous state game on the previous node on the quest.
If not, any work around you may think?
Thanks.
With the save system, is it possible to restore to a previos state without loading?
What I wont is to restore the state of all my objects to a state that I already saved reaching a node on the quest.
For instance on my game if the player dies, it destroys, but I don't load the scene again (its an open world and it takes a while to load it), so I'd like to call the save system and "load" the previous state game on the previous node on the quest.
If not, any work around you may think?
Thanks.
Re: Restoring a previous state
Hi,
You can certainly restore quest states and GameObject positions. But if you've destroyed an object, Quest Machine's save system will not bring it back. It assumes that you're going to reload the scene to get the original objects back. After reloading the scene, the save system's Persistent Destructible component will check if the GameObject has been marked as destroyed in the saved game. If so, it will destroy the GameObject.
What if you break the scene into smaller parts? You can use something like SECTR Stream to stream in pieces of the world as the player moves around.
You can certainly restore quest states and GameObject positions. But if you've destroyed an object, Quest Machine's save system will not bring it back. It assumes that you're going to reload the scene to get the original objects back. After reloading the scene, the save system's Persistent Destructible component will check if the GameObject has been marked as destroyed in the saved game. If so, it will destroy the GameObject.
What if you break the scene into smaller parts? You can use something like SECTR Stream to stream in pieces of the world as the player moves around.
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Restoring a previous state
Ok, if I reload the scene, I guess I need also 2 different states (I think we need therefore 2 saving slots)
- In case the player quits the game, once he comes back everything must be on the same position and the same enemies killed, so we should save the game on the slot "quit game" and load again the slot "quit game" once he is back.
- In case the player dies, the scene reloads and I want the player on the BEGGINING (Start) of the Node / Quest he was in, so once the Scene reloads everything must be at the same position and none enemies killed, as it was at the beginning of this Node. So we should save the game on the slot "player death" and load again the slot "player death" once he is back.
Is this ok? what's the code do I need and where to accomplish that? Thanks
- In case the player quits the game, once he comes back everything must be on the same position and the same enemies killed, so we should save the game on the slot "quit game" and load again the slot "quit game" once he is back.
- In case the player dies, the scene reloads and I want the player on the BEGGINING (Start) of the Node / Quest he was in, so once the Scene reloads everything must be at the same position and none enemies killed, as it was at the beginning of this Node. So we should save the game on the slot "player death" and load again the slot "player death" once he is back.
Is this ok? what's the code do I need and where to accomplish that? Thanks
Re: Restoring a previous state
Hi,
Let's say you define the slot numbers like this:
When the player quits, save to SavedGameSlot. It would be best to put this in a save/load/quit menu. But as a quick test you can do this:
To resume the game:
When a quest becomes active, save to RestartQuestSlot:
When the player dies, reload RestartQuestSlot:
Let's say you define the slot numbers like this:
Code: Select all
public const int SavedGameSlot = 0;
public const int RestartQuestSlot = 1;
Code: Select all
void OnApplicationQuit() {
PixelCrushers.SaveSystem.SaveToSlot(SavedGameSlot);
}
Code: Select all
PixelCrushers.SaveSystem.LoadFromSlot(SavedGameSlot);
When a quest becomes active, save to RestartQuestSlot:
Code: Select all
using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
public class MyScript : MonoBehaviour, IMessageHandler) {
void OnEnable() { // Let me know when quest states change.
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage);
}
void OnDisable() { // Unregister when disabling script.
MessageSystem.RemoveListener(this);
}
void OnMessage(MessageArgs messageArgs) {
var state = (QuestState)messageArgs.values[1];
if (messageArgs.values[0] != null) {
// Is a node. We don't care, so exit.
return;
}
if (state == QuestState.Active) { // Quest became active. Save game.
SaveSystem.SaveToSlot(RestartQuestSlot);
}
}
Code: Select all
SaveSystem.LoadFromSlot(RestartQuestSlot);
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Restoring a previous state
ok, great!!
The following: if (state == QuestState.Active) I guess is only for the general quest, not for the individual nodes, is that correct? If so, how it would be for checking that a Node (And not the full Quest) is just Active.
And I'd like to do it preferibly only for the Main Quests, how can I ask if a quest is from the group "Main" ?
In case I want to craft manually which Nodes on every quest I want to save the state, is there any action on the editor to do so? I don't remember now....
The following: if (state == QuestState.Active) I guess is only for the general quest, not for the individual nodes, is that correct? If so, how it would be for checking that a Node (And not the full Quest) is just Active.
And I'd like to do it preferibly only for the Main Quests, how can I ask if a quest is from the group "Main" ?
In case I want to craft manually which Nodes on every quest I want to save the state, is there any action on the editor to do so? I don't remember now....
Re: Restoring a previous state
Hi,
(Edit: Quests use QuestState. Quest nodes use QuestNodeState. I fixed my code above.)
The QuestMachineMessages class explains all of the messages. Scroll down to "Public Attributes", and click on a message to get more information. For example, this is the information for the QuestStateChangedMessage:
Sent when a quest state or quest node state changes.
The message is sent when a quest or quest node state changes. The quest node is in messageArgs.values[0]. Its type is StringField. The example below only saves if the quest ID is "Bake Pie" and the node ID is "Get 5 Apples":GorkaGames wrote: ↑Mon Oct 15, 2018 2:09 pmThe following: if (state == QuestState.Active) I guess is only for the general quest, not for the individual nodes, is that correct? If so, how it would be for checking that a Node (And not the full Quest) is just Active.
Code: Select all
public void OnMessage(MessageArgs messageArgs) {
StringField nodeID = messageArgs.values[0] as StringField;
if (nodeID == null) {
return; // Is main quest. We're only looking for the "Get 5 Apples" node.
}
QuestNodeState state = (QuestNodeState)messageArgs.values[1];
if (messageArgs.parameter == "Bake Pie" && nodeID == "Get 5 Apples" && state == QuestNodeState.Active) {
SaveSystem.SaveToSlot(RestartQuestSlot);
}
}
The QuestMachineMessages class explains all of the messages. Scroll down to "Public Attributes", and click on a message to get more information. For example, this is the information for the QuestStateChangedMessage:
Sent when a quest state or quest node state changes.
- Parameter: Quest ID.
- Argument 0: [StringField] Quest node ID, or blank for main quest state.
- Argument 1: [QuestState] / [QuestNodeState] New state.
Check the Quest's group property:GorkaGames wrote: ↑Mon Oct 15, 2018 2:09 pmAnd I'd like to do it preferibly only for the Main Quests, how can I ask if a quest is from the group "Main" ?
Code: Select all
Quest quest = QuestMachine.GetQuestInstance("Bake Pie");
if (quest.group == "Main") {
Debug.Log("This is a Main quest.");
}
No, sorry. When you save a quest, it saves the state of the quest, the states of all of the nodes, and the values of the counters.GorkaGames wrote: ↑Mon Oct 15, 2018 2:09 pmIn case I want to craft manually which Nodes on every quest I want to save the state, is there any action on the editor to do so? I don't remember now....
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Restoring a previous state
Ok, so I guess this is finally the code to save when a NODE gets active:
I'm getting 2 errors:
1. IMessageHandler Can't implement because its not public
2. AddListener Not possible 2 Arguments
NOTE: I think this can be a nice feature also for your product, people will love to save the game on every Node automatically (as control points automatically)
using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
public class MyScript : MonoBehaviour, IMessageHandler) {
void OnEnable()
{ // Let me know when quest states change.
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage);
}
void OnDisable()
{ // Unregister when disabling script.
MessageSystem.RemoveListener(this);
}
void OnMessage(MessageArgs messageArgs)
{
//Recoge Cambio en el estado de una Quest
//QuestState state = (QuestState)messageArgs.values[1];
//Recoge Cambio en el estado del nodo de una Quest
QuestNodeState state = (QuestNodeState)messageArgs.values[1];
StringField nodeID = messageArgs.values[0] as StringField;
if (nodeID == null)
{
return; // Is main quest.
}
//Comprueba si es activa la quest
//if (state == QuestState.Active)
//Comprueba si es activa el nodo de la quest
if (state == QuestNodeState.Active)
{ // Quest Node became active. Save game.
//Guardamos en el slot 0, que lo reservamos para guardar los estados de cambios de Nodos / quests
SaveSystem.SaveToSlot(0);
Debug.Log("Save Quest Node");
if (Invector.vCharacterController.vHUDController.instance)
Invector.vCharacterController.vHUDController.instance.ShowText("Save Quest Node");
}
}
}
I'm getting 2 errors:
1. IMessageHandler Can't implement because its not public
2. AddListener Not possible 2 Arguments
NOTE: I think this can be a nice feature also for your product, people will love to save the game on every Node automatically (as control points automatically)
using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
public class MyScript : MonoBehaviour, IMessageHandler) {
void OnEnable()
{ // Let me know when quest states change.
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage);
}
void OnDisable()
{ // Unregister when disabling script.
MessageSystem.RemoveListener(this);
}
void OnMessage(MessageArgs messageArgs)
{
//Recoge Cambio en el estado de una Quest
//QuestState state = (QuestState)messageArgs.values[1];
//Recoge Cambio en el estado del nodo de una Quest
QuestNodeState state = (QuestNodeState)messageArgs.values[1];
StringField nodeID = messageArgs.values[0] as StringField;
if (nodeID == null)
{
return; // Is main quest.
}
//Comprueba si es activa la quest
//if (state == QuestState.Active)
//Comprueba si es activa el nodo de la quest
if (state == QuestNodeState.Active)
{ // Quest Node became active. Save game.
//Guardamos en el slot 0, que lo reservamos para guardar los estados de cambios de Nodos / quests
SaveSystem.SaveToSlot(0);
Debug.Log("Save Quest Node");
if (Invector.vCharacterController.vHUDController.instance)
Invector.vCharacterController.vHUDController.instance.ShowText("Save Quest Node");
}
}
}
Re: Restoring a previous state
Hi,
If that doesn't work, then your project may have another IMessageHandler from another asset. In this case, specify the PixelCrushers one:
IMessageHandler is public. It looks like you may have a typo. Try removing the ")" after it:GorkaGames wrote: ↑Wed Oct 17, 2018 4:40 pm1. IMessageHandler Can't implement because its not public
Code: Select all
public class MyScript : MonoBehaviour, IMessageHandler {
Code: Select all
public class MyScript : MonoBehaviour, PixelCrushers.IMessageHandler {
MessageSystem.AddListener() expects three arguments. The third argument is the message parameter. If you want to ignore the message parameter, pass null:
Code: Select all
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage, null);
I'll make a note for the next version after 1.0.8. I'm not adding any new features to 1.0.8 because I'm trying to release it as soon as possible. Only a few third party integrations are left to complete for 1.0.8.GorkaGames wrote: ↑Wed Oct 17, 2018 4:40 pmNOTE: I think this can be a nice feature also for your product, people will love to save the game on every Node automatically (as control points automatically)
(fixed call to MessageSystem.AddListener, OnMessage public)
Code: Select all
using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
public class MyScript: MonoBehaviour, PixelCrushers.IMessageHandler {
void OnEnable() { // Let me know when quest states change.
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage, string.Empty);
}
void OnDisable() { // Unregister when disabling script.
MessageSystem.RemoveListener(this);
}
public void OnMessage(MessageArgs messageArgs) {
//Recoge Cambio en el estado de una Quest
//QuestState state = (QuestState)messageArgs.values[1];
//Recoge Cambio en el estado del nodo de una Quest
QuestNodeState state = (QuestNodeState) messageArgs.values[1];
StringField nodeID = messageArgs.values[0] as StringField;
if (nodeID == null) {
return; // Is main quest.
}
//Comprueba si es activa la quest
//if (state == QuestState.Active)
//Comprueba si es activa el nodo de la quest
if (state == QuestNodeState.Active) { // Quest Node became active. Save game.
//Guardamos en el slot 0, que lo reservamos para guardar los estados de cambios de Nodos / quests
SaveSystem.SaveToSlot(0);
Debug.Log("Save Quest Node");
if (Invector.vCharacterController.vHUDController.instance)
Invector.vCharacterController.vHUDController.instance.ShowText("Save Quest Node");
}
}
}
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Restoring a previous state
I have updated the code but the same. Those arre the errors on the editor: (I have already updated to the beta you sent me). Add Listener is with errors also in Visual Studio-The call is ambiguous:
Assets/Scripts/Quests/QuestNodeControllerSaver.cs(11,23): error CS0121: The call is ambiguous between the following methods or properties: `PixelCrushers.MessageSystem.AddListener(PixelCrushers.IMessageHandler, string, string)' and `PixelCrushers.MessageSystem.AddListener(PixelCrushers.IMessageHandler, string, PixelCrushers.StringField)'
Assets/Scripts/Quests/QuestNodeControllerSaver.cs(6,14): error CS0737: `QuestNodeControllerSaver' does not implement interface member `PixelCrushers.IMessageHandler.OnMessage(PixelCrushers.MessageArgs)' and the best implementing candidate `QuestNodeControllerSaver.OnMessage(PixelCrushers.MessageArgs)' is not public
Assets/Scripts/Quests/QuestNodeControllerSaver.cs(11,23): error CS0121: The call is ambiguous between the following methods or properties: `PixelCrushers.MessageSystem.AddListener(PixelCrushers.IMessageHandler, string, string)' and `PixelCrushers.MessageSystem.AddListener(PixelCrushers.IMessageHandler, string, PixelCrushers.StringField)'
Assets/Scripts/Quests/QuestNodeControllerSaver.cs(6,14): error CS0737: `QuestNodeControllerSaver' does not implement interface member `PixelCrushers.IMessageHandler.OnMessage(PixelCrushers.MessageArgs)' and the best implementing candidate `QuestNodeControllerSaver.OnMessage(PixelCrushers.MessageArgs)' is not public
Re: Restoring a previous state
Sorry, use string.Empty instead of null.