Saving the Player's name

Hello there,

I’ve made the menu, for the character creation and I’ve added the name inside the PlayerConverstant class, so I’ve implemented the ISaveable interface which can’t be more simple

 public object CaptureState()
{
            return playerName;
}

public void RestoreState(object state)
{
            playerName = (string)state;
}

But when the ingame scene gets loaded the PlayerConversant variable still the default one.
Maybe I forget how it works, but shouldn’t the name be restored on the fly as soon as the PersistentGameObject get loaded? :thinking:

Also, the variable inside the PlayerConversant gets updated during the character creation, so this part is fine.

Is there a way to debug/read all the saved data in the save file? :thinking:
Anyway the string is present in the save file

#GranDucato.Dialgue.PlayerConversantE Pippo​ºÿÿÿüÿÿÿ

Where are you setting the default name for the Player? If it’s in Start(), then it will overwrite the RestoreState value.

Nope, it’s in the variable declaration
string PlayerName =“Player”
… I’ll try leave it empty

Only if you use my Json system.

Paste in your PlayerConversant.cs… there might be something hiding in there we’re missing.

There’s nothing special in the PlayerConversant, but as you may know there’s nothing better than the debug to understand what is going on, and indeed, I notice that the RestoreState method is never get called, so during the debugging I’ve set a breackpoint in playerName = (string)state; and I’ve never get on it :frowning:

Could it be, because the PlayerConversant is after the SavingEntity?

public class PlayerConversant : MonoBehaviour, ISaveable
{
[SerializeField] string playerName = "Player";
        
        public GameObject conversantCamera;
        Dialogue currentDialogue;
        DialogueNode currentNode = null;
        AIConversant currentConversant = null;
        AIConversant targetConversant;
        bool isChoosing = false;

        public event System.Action onConversationUpdated;
        Mover mover = null;

        private void Start()
        {
            mover = GetComponent<Mover>();
        }

        private void Update()
        {
            if (targetConversant)
            {
                if (Vector3.Distance(transform.position, targetConversant.transform.position) > 3f)
                {
                    mover.MoveTo(targetConversant.transform.position);
                }
                else
                {
                    mover.Cancel();
                    StartDialogue();
                }
            }
        }

        public void StartDialogueAction(Dialogue dialogue, AIConversant speaker)
        {
            //Debug.Log($"StartDialogueAction {speaker}/{dialogue}");
            if (currentConversant != null && currentConversant == speaker) return;
            if (currentDialogue != null) QuitDialogue();
            if (dialogue == null)
            {
                return;
            }

            GetComponent<ActionScheduler>().StartAction(this as IAction);
            targetConversant = speaker;
            currentDialogue = dialogue;
        }

        public void StartDialogue()
        {
            currentConversant = targetConversant;
            targetConversant = null;
            currentNode = currentDialogue.GetRootNode();
            TriggerEnterAction();
            onConversationUpdated();
        }

        public void QuitDialogue()
        {
            currentDialogue = null;
            TriggerExitAction();
            currentNode = null;
            isChoosing = false;
            currentConversant = null;
            onConversationUpdated();
        }

        public bool IsActive()
        {
            return currentDialogue != null;
        }

        public bool IsChoosing()
        {
            return isChoosing;
        }

        public void SetPlayerName(string value)
        {
            playerName = value;
        }

        public string GetPlayerName()
        {
            return playerName;
        }

        public string GetCurrentConversantName()
        {
            if (isChoosing)
                return playerName;
            else
                return currentConversant.GetConversantName();
        }

        public GameObject GetCurrentConversantGO()
        {
            if (isChoosing)
                return gameObject;
            else
                return currentConversant.gameObject;
        }

        public string GetText()
        {
            if (currentNode == null)
            {
                return "";
            }

            return currentNode.GetText();
        }

        public IEnumerable<DialogueNode> GetChoices()
        {
            return FilterOnCondition(currentDialogue.GetPlayerChildren(currentNode));
        }

        public void SelectChoice(DialogueNode chosenNode)
        {
            currentNode = chosenNode;
            TriggerEnterAction();
            isChoosing = false;
            Next();
        }

        public void Next()
        {
            int numPlayerResponses = FilterOnCondition(currentDialogue.GetPlayerChildren(currentNode)).Count();
            if (numPlayerResponses > 0)
            {
                isChoosing = true;
                TriggerExitAction();
                onConversationUpdated();
                return;
            }

            DialogueNode[] children = FilterOnCondition(currentDialogue.GetAIChildren(currentNode)).ToArray();
            int randomIndex = Random.Range(0, children.Count());
            TriggerExitAction();
            currentNode = children[randomIndex];
            TriggerEnterAction();
            onConversationUpdated();
        }

        public bool HasNext()
        {
            return FilterOnCondition(currentDialogue.GetAllChildren(currentNode)).Count() > 0;
        }

        /// <summary>
        /// Avoid certain DialogueNode if player is already in a Quest.
        /// </summary>
        /// <param name="inputNode">Dialogue Node</param>
        /// <returns></returns>
        private IEnumerable<DialogueNode> FilterOnCondition(IEnumerable<DialogueNode> inputNode)
        {
            foreach (var node in inputNode)
            {
                if (node.CheckCondition(GetEvaluators())) yield return node;
            }
        }

        private IEnumerable<IPredicateEvaluator> GetEvaluators()
        {
            return GetComponents<IPredicateEvaluator>();
        }

        private void TriggerEnterAction()
        {
            if (currentNode != null)
            {
                TriggerAction(currentNode.GetOnEnterAction());
            }
        }

        private void TriggerExitAction()
        {
            if (currentNode != null)
            {
                TriggerAction(currentNode.GetOnExitAction());
            }
        }

        private void TriggerAction(string action)
        {
            if (action == "") return;

            foreach (DialogueTrigger trigger in currentConversant.GetComponents<DialogueTrigger>())
            {
                trigger.Trigger(action);
            }
        }

        #region ==== SAVING SYSTEM ================================================================

        public object CaptureState()
        {
            return playerName;
        }

        public void RestoreState(object state)
        {
            playerName = (string)state;
        }

        #endregion 
    }

No, that should affect nothing…
Put a Debug.Log in the SaveableEntity’s CaptureState and RestoreState in the foreach loop… .let’s make sure the Capture and Restore are being called for each ISaveable

1 Like

Yea, that’s a good plan, indeed we get the data saved, but not restored, so looks like the problem is when we have loaded the next scene :thinking:

image

Also, the Persistent gameObject is present and the booth SavingSystem and SavingWrapper are present.

Also, if I load the save the name is loaded correctly!

[EDIT]
Ok I’ve made a couple of tests, to make it dirty I could do something like:

 private IEnumerator LoadFirstScene()
        {
            Fader fader = FindObjectOfType<Fader>();
            yield return fader.FadeOut(fadeOutTime);
            yield return SceneManager.LoadSceneAsync(firstSceneBuildIndex);
            Load();
            yield return fader.FadeIn(fadeInTime);
        }

But if you have better solution, please tell it :pray::sweat_smile:

Hmmm… I’m thinking I didn’t ask the right questions…

Ok, so the name is set in the MainMenu, then you LoadFirstScene()… but… in our course LoadFirstScene() we never Restore() because we really didnt’ cover things like player customization in the main menu in the ShopsAbilities course…

So the LoadFirstScene() coroutine doesn’t Load() because it doesn’t think it needs to… Of course, if you Save in the game in Continue or move between scenes, the default “Player” is saved because that’s what it knows…

If that’s the case, then your solution is the correct solution.

1 Like

Ok I’ve made a couple of tests, to make it dirty I could do something like:

 private IEnumerator LoadFirstScene()
        {
            Fader fader = FindObjectOfType<Fader>();
            yield return fader.FadeOut(fadeOutTime);
            yield return SceneManager.LoadSceneAsync(firstSceneBuildIndex);
            Load();
            yield return fader.FadeIn(fadeInTime);
        }

Fine then, so we close this case too :wink:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms