Saving system , Multiply saves from Start menu , Create new game , load game

Hello all

Im trying to think how to start something like this
and looking for help insights on the matter
Basically i want to have in the start menu 3 different saves for now
It can start a new game and save it , or load an existing save
If also you can help me with after pressing the new game to have choose Character or class that changes the character will also love the help with that
i already have Different classes
But how can i make a model of the player different after he pressed the new game then have 3 different classes and move between the models

Thank you for the help much appreciated

For the first question, that of multiple saves… if you know you’ll have three slots, you could easily save the slot to PlayerPrefs

Then when saving/loading, use the filename $"save{PlayerPrefs.GetInt("Slot").sav"

I think the best solution to character selection is to have all three of the prefabs for your player in your player prefab. Disable all three, then enable the correct prefab at runtime based on whatever you’ve stored as the “character” (I’d just store that as an integer). You’ll also need to set the correct avatar in the Animator.

You mean to have all 3 models ?
What about creating a character ?
like having 3 different class a mage a warrior and a shaman lets say

But have different model show each time you choose
to make a scene where the player stands and just switch the models ?

then take what ever input he made save that as that and load that model and save for the first time when start a new game ?

About the slots i didnt think about it thats a very nice idea and can still work with that
after finish choosing a class it still a save in slot 1 or slot 2
just different character different class

I’m still assuming you’re talking about one model for the mage, one for the warrior, and one for the shaman…
So your new character selection scene, you want to have a character with the Player Controller disabled, usually set in an appropriate setting with the camera facing the character.
You’ll need some sort of script like a CharacterSelector that will also be on the players in the other scenes (just put it on the prefab). In the selection scene, have a serialized bool isChoosingCharacter set (and not set in the other scenes). That’s the class you’ll use to manage the selection of the charcter. Your AI will have portraits (buttons) of the available characters, and when you click on the portrait, the appropriate class is selected.
Your character selector will then set the class in BaseStats, deactivate the character models, and activate the appropriate character model. It will also set the appropriate character avatar, if the characters are based on different avatars.
Then when you start the game, delete any existing save file in the selected slot, and save the game. At this point, only the player’s information will be saved. That’s ok, because when you move into the beginning scene, you’ll load the player’s info from the load file and begin the game.

1 Like

Wow brian how your brain work is like crazy

So more questions
Why not work with the saving system in the CharacterSelection scene By the way what i did for now is
Have Both UI of Choose a Save and Choose a Character in the same Scene
The Start Scene will be just a splash scene that you press and load this scene everything will work from here

So , first you choose a save or continue where you start
so i made this in the SavingSystem

public bool FileExists(string saveFile)
        {
            string path = GetPathFromSaveFile(saveFile);
            return FileExists(path);
        }

And i want to put a Script on the Save Panel UI
that check if saveSlot1/2/3 exists
if it does to do Continue and just load the scene with the Load from Saving System

Now for saving for the first time Lets say The player press Slot1
And choose Character1
So i need those both integers to save to use the PlayerPrefs for that?
then when i Load the Scene i Save the game as saveSlot1 with checking in the CharacterSelector that now isnt True anymore
And i enable again like i did in the CharacterSelection scene the model and i get the CharacterIndex from the PlayerPrefs and assign it then Save for the first time using the SavingSystem , of course before that Delete any savefile of saveSlot1

Another question i have is what about the The hands for the transforms in the figther isnt changing the model will effect that ?

Also i dont understand lets say after i choose the save file and character
and i press Start before i load the Scene i delete the savefile1 lets say for slot 1
save a new savefile1 from the SavingSystem ?
have a saving system object in the scene and save using that ?
i really dont understand how to do it
and if it is like that why i need this playerprefs anyway ?
i can just do a new SavingWrapper of Save and give it a name based on the one i pressed i have all that info

Thank you so much for helping me with this
i really appreciate your help with everything

Yes, you’ll need to set the hand transforms.
There are four approaches for this:

  • You could register the Hand Transforms for each character in the CharacterSelector script
  • You could have a script on each character’s roots that register the hand transforms in OnEnable
  • You could have a script on each hand transform that registers itself in OnEnable.
  • You could have an empty gameobject childed to each hand transform that Fighter can search for.

The ideal approach is the second one, at least in my crazy brain. A script at the root of each character would be responsible for setting the Animator’s avatar (GetComponentInParent), the fighter’s hand transforms, and anything I might have missed. This leaves the character selector just responsible for deactivating all the characters and then activating the correct character (which triggers that character’s OnEnable() and lets it do it’s job.
You’ll also need a method in Fighter to SetHandTransforms(Transform right, Transform left);

I’ll get to the rest later, you wrapped a lot of questions in that reply. :slight_smile:

Thanks for the help , yeah i know its a lot of questions
in the end i will do a summary with photos and all and explanation for others dont worry
im sure it will be useful for other people here in the RPG

the OnEnable yeah it could work
what im trying now to do is have another object in the scene that is the SavingSystem and when he chose the slot and the character and pressed the button start
what i will do is delete saveslot1 save saveslot1.sav
then Load Scene 2 which is the start of the game
but i also need the fader to make it look nice and all

Edited Update

So for now what i did is Disable the awake in SavingWrapper because it causes me to freeze unity in the Scene of Character Selection
i dont understand why it is causing this maybe because there isnt a persistent object i really dont know

In my Scene i have an object called SceneLoader which have 2 Childs
The saving prefab and fader
the scene loader loads the sandbox scene Switch the models saves with the new Save methods in Saving wrapper that i added for making it according to the slots

The On Enable in each model prefab is setting the hand transforms

The problems i have after loading the new scene the new model exist
The animations isnt working its just flying over the terrain
if i go into portals i need to have a way of knowing which slot i am right now
where to save that slot index in the player ?

Also i how i fix the animations ?
How i fix the Awake in saving wrapper to not freeze everything in the character selection scene

Im on this thing for a few days and i really dont understand what to do

I followed your help
in my Player Prefab
i have 4 different models all from Fantasy Hero Synthy its the one with all the modulars
one is the normal one i used for now
and 3 others which i want to be the changes
In my player prefab i have the CharacterSelector
i still dont understand why you meant to make a bool i didnt use that for the switching
they press a button and i switch characters then when press start
it loads the scene like in the portal script
get the starting position of the new Player in the scene

public void StartNewGame()
    {
        StartCoroutine(LoadNewGame());
    }

    IEnumerator LoadNewGame()
    {
        if (sceneToLoad < 0)
        {
            Debug.LogError("Scene to load not set.");
            yield break;
        }

        DontDestroyOnLoad(transform.root.gameObject);
        PlayerController playerController = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
        playerController.enabled = false;
        //Remove control player

        yield return fader.FadeOut(fadeOutTime);

        savingWrapper.NewSaveFile(saveMenu.GetSlotIndex());

        yield return SceneManager.LoadSceneAsync(sceneToLoad);
        PlayerController newPlayerController = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
        newPlayerController.enabled = false;
        //Change Player Character
        Vector3 startPos = newPlayerController.GetStartPos();
        savingWrapper.LoadFromMenu(saveMenu.GetSlotIndex());
        newPlayerController.GetComponent<NavMeshAgent>().Warp(startPos);
        newPlayerController.GetComponent<CharacterSelector>().ChangeCharacterModel(character.GetCurrentIndex());
        yield return new WaitForSeconds(fadeWaitTime);
        fader.FadeIn(fadeInTime);
        newPlayerController.enabled = true;
        savingWrapper.NewSaveFile(saveMenu.GetSlotIndex());
        Destroy(gameObject); 
    }

here is the code

newPlayerController.GetComponent<CharacterSelector>().ChangeCharacterModel(character.GetCurrentIndex());

This should be the responsibility of a component on the player.

public class CharacterSelector:MonoBehavior, ISaveable
{
     [SerializeField] List<Transform> models=new List<Transform>;
     int currentCharacter=0;

    void Awake()
    {
          ApplyCurrentCharacter(); //default to character 0 until set or restoreState
    }

     public int SetCurrentCharacter(int character)
     {
          currentCharacter=character;
          ApplyCurrentCharacter();
      }

      void ApplyCurrentCharacter()
      {
            foreach(Transform model in models)
            {
                 model.gameObject.SetActive(false);
            }
            model[currentCharacter].gameObject.SetActive(true);
      }


     public object CaptureState()
     {
            return currentCharacter;
     }
    
     public void RestoreState(object state)
     {
           currentCharacter = (int)state;
           ApplyCurrentCharacter()
     }

When you initially save in a blank save file, this will be saved automatically with the player (as this script is ON the player.
The same with the portals, when you transition between scenes, the data is saved between players.

It’s probably freezing because of exactly that… load the persistent object prefab in the main menu in the same way it’s loaded in the other scenes. Kill that Awake method in SavingWrapper, you want to control whether you load the last scene through the menu.
Since the SavingWrapper will now be loaded (along with Fader and SavingSystem) you can now simply call LoadLastScene() if the player elects to resume a game from a save file, or you can start the new scene by calling StartNewGame()

Since this is the LoadNewGame, you already know the correct scene index is 1 (0 is main menu, 1st scene, 1 is sandbox, starting scene)

Well i tried it

In the Character Selection scene its switching everything fine
Now after the sandbox is loaded it isnt changing the characters
and now it just show in the sandbox the default character and the animations isnt working :confused:

Also i tried saving the current saveSlotIndex in the saving wrapper and setting it each time
and i feel i am just keep doing weird stuff and breaking everything

Also i Created an object in the main Menu Called PersistentObjectSpawner i put there the PersistentObjectsSpawner script with the PersistenObjects prefab
Deleted the Script in the Core prefab
So have only 1 of that starts in the main menu for the whole project
From the SceneLoader Object i had i deleted the 2 children that had the fader and saving prefab
because now i have them from the persistenObjects

I really love that you help i feel so lost with this
5 days i am on this and my spirit is falling
but i know we can do it !

This is now my saving wrapper

public class SavingWrapper : MonoBehaviour
    {
        const string defaultSaveFile = "Autosave";
        const string newSaveFile = "SaveSlot";
        [SerializeField] float fadeInTime = 0.2f;

        int saveSlotIndex = 0;

        IEnumerator LoadLastScene()
        {
            Debug.Log("LoadingLastScene");
            yield return GetComponent<SavingSystem>().LoadLastScene(newSaveFile + saveSlotIndex);
            Fader fader = FindObjectOfType<Fader>();
            fader.FadeOutImmediate();
            yield return fader.FadeIn(fadeInTime);
        }

        // Update is called once per frame
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.L))
            {
                Load();
            }

            if (Input.GetKeyDown(KeyCode.S))
            {
                Save();
            }

            if (Input.GetKeyDown(KeyCode.D))
            {
                Delete();
            }

        }

        public void SetSlotIndex(int index)
        {
            saveSlotIndex = index;
        }

        public void Delete()
        {
            GetComponent<SavingSystem>().Delete(newSaveFile + saveSlotIndex);
        }

        public void Load()
        {
            //Call to saving system to load
            GetComponent<SavingSystem>().Load(newSaveFile + saveSlotIndex);            
        }

        public void Save()
        {
            //Call to saving system to save
            GetComponent<SavingSystem>().Save(newSaveFile + saveSlotIndex);
        }

        public void NewSaveFile(int index)
        {
            GetComponent<SavingSystem>().Save(newSaveFile + index);
        }

        public void LoadFromMenu(int index)
        {
           GetComponent<SavingSystem>().Load(newSaveFile + index); 
        }

        public void LoadLastSave()
        {
            StartCoroutine(LoadLastScene());
        }

        public bool FileExists(int index)
        {
            return GetComponent<SavingSystem>().FileExists(newSaveFile + index);
        }
    }

This is the save Menu UI
where you pick the Slots before it open the character Menu

public class SaveMenu : MonoBehaviour
{
    [SerializeField] GameObject characterPanel;
    [SerializeField] GameObject backButton;
    [SerializeField] GameObject startButton;
    [SerializeField] Transform player;

    int slotIndex = 1;
    const string savefileName = "saveSlot";
    SavingWrapper savingWrapper;

    private void Awake() 
    {
        savingWrapper = FindObjectOfType<SavingWrapper>();
    }

    public void ChooseCharacter(int index)
    {
        if (savingWrapper.FileExists(index))
        {
            savingWrapper.SetSlotIndex(index);
            savingWrapper.LoadLastSave();
        }
        
        slotIndex = index;
        gameObject.SetActive(false);
        characterPanel.SetActive(true);
        backButton.SetActive(true);
        startButton.SetActive(true);
    }

    public void OpenSaveMenu()
    {
        gameObject.SetActive(true);
        characterPanel.SetActive(false);
        backButton.SetActive(false);
        startButton.SetActive(false);
    }

    public int GetSlotIndex() {return slotIndex;}
}

Do you have the CharacterSelection script on all of your Players (i.e. in each scene?)

I attached it on the player prefab
My player prefab have all those models too inside of it

After the talk On discord
This is the link for the github Check the commit on Dev branch as i moved there long time ago and didnt do any merge

So i fixed the problem with the Switching in the end it was the unique identfier for some reason it was Player and not player in the CharacterSelector

Now i tried fixing the animations with Retargeting of Humanoid animations

But this gives me so many errors with using some of animations because the Animator now sits in each Child
and it feels so weird

Is there a way to have the Animator stay on the parent which is the Player and still work all those animations ?
feels like it get broken like that and the Player just fly away on the terrain instead of doing any animations

I find the animator is best on the parent. It knows how to crawl the heirarchy to find the relevant bones.

Since your characters all share the same skeleton (Fantasy Modular Hero), you should be able to just have the one skeleton, and only activate/deactivate the models. I would remove the animators from the child objects altogether and just stick with the one in the root.

I tried that but for no luck its not working
I thought it will work too
Any other advice what to do ?
What happens if you do that when switching models they stay in the T model and just hover over the ground

Post a screenshot of your player’s inspector with the animator expanded in the root.

I can confirm that even our course project puts the animator in the root, and I use the Fantasy Modular Hero in my published game, and the animator is in the root.

Also, it might be handy to see your player’s heirarchy, though that might take a few screenshots…

To clarify, what I’m interested in with the player’s heirarchy is seeing the root of each character and the root of the bones

Unity_n66DVLJYcl

is this ok ?
Each model have that script on him for changing the hands in the fighter they dont have animators inside of them

Ok, I want to try an experiment… if you have source control, this would be a GREAT place to commit…

I believe what may be happening is that activated or not, the Animator is finding the first set of bones and using it regardless, in which case, due to scope, the Animator would be using the Root on Preset 95, and your active preset may be 61, but the 95 root can’t “see” the 61… This means that the transforms on 61 won’t get moved… but the MeshRenderers for the models under 61 are looking to 61’s root for instructions on how to deform the mesh.

In this interesting case, all of your characters are, in fact, using the same Skeleton, so this is the insanity I am proposing…

I would do this in the sandbox scene, and not apply it back to the player prefab until it works.

First, for each of the presets, right click on the preset and select Prefab/Unpack Prefab Completely. You’ll need to do this so that you can move/delete elements.

Then for each preset, move any important scripts (I believe we discussed a script that sets the fighter’s hands in OnEnable, and sets the avatar, but if I’m right we won’t need this script at all) from the Preset_xx GameObject to the Modular Characters GameObject. You might also rename the Modular Characters GameObjects to something a bit more meaningful. “Adventurer”, “Rogue”, “Knight”, “Mage”, etc.

Now for the scary part…
Drag the Modular Characters out of the Chr_FantasyHero_Preset_x gameobject, so that they sit at the same level as the Audio Sources.
Finally, drag the last Root out of the preset. Just one root, no more, no less.
Then delete each of the Chr_Fantasy gameobjects…
Your new player will look something like this:


(this is a mockup, my player actually activates/deactivates his/her body parts based on the equipped itmes and gender of the character, but that script is about 1200 lines of madness).

Now in your Character Selector script, drag the new model trees into the array. The root will always stay active.

This means that

  • The hand transforms will never change
  • The Avatar will never change.

The animator should be in the root of the player.

Once you get this madness to work properly, then (and only then), can you apply these changes to the prefab.

Update for anybody reading this thread: Don’t do what I just suggested in the last paragraph, it doesn’t work.

Hello all and thanks for following this post this has been fun , and thanks for brian for all the help

So to explain how everything was done :
First Create a Character Selection Scene
What does it mean Create a scene build another world or maybe you already have from another scene
with terrain and all put a player Prefab there with a camera Facing the player Prefab so when you will be switching the models thats what the Player playing will game will see

Inside this scene have a Save Menu and Character Menu UI , Start Button and Back Button
So you will need to Create a Canvas with a Save Menu Panel and a Character Menu panel
The save menu will control which slot index you have given by input by each button for make it easy i did it by 1 2 3 ( see Photos below the Section )
He will also Be in charge of Closing the panel of the Character menu and Save Menu

So I made it simple 3 buttons in each panel the character and the save menu
The buttons in the Save Menu call a method in the SaveMenu script that sits on the Save panel
Which does a simple thing
Updating the slotIndex by the button input 1 - 3
disabling the save panel
enabling the Character panel
enabling the back button and start button which are for the Character panel
Back is for go back to the save menu panel
start is for loading a new game and save a new save file from the slot index we got before
we will talk later what happen after the start.

public void ChooseCharacter(int index)
    {

        if (savingWrapper.FileExists(index)) // Dont mind this for now , we will get back to that later
        {
            savingWrapper.SetSlotIndex(index);
            savingWrapper.LoadLastSave();
            gameObject.SetActive(false);
            return;
        }

        slotIndex = index;
        gameObject.SetActive(false);
        characterPanel.SetActive(true);
        backButton.SetActive(true);
        startButton.SetActive(true);
    }

In the Character Menu
You will build it quite Similar with 3 buttons For switching the models
Of course here now you will see the Back button and the start button
So first will do it simple and explain about the back button
The back button what it does is similar to the Saveslot button we pressed before
it is enabling the save panel to be alive again
disabling the character panel
disabling the back and start button

public void OpenSaveMenu()
    {
        gameObject.SetActive(true);
        characterPanel.SetActive(false);
        backButton.SetActive(false);
        startButton.SetActive(false);
    }

Now up until here everything is quite simple playing with UI opening closing
Now starts the fun

So we will need to Create on the player prefab a new Class Called CharacterSelector
After trying many different types of stuff and help with brian
We saw many problems with switching models that are on the player already which i think i have a fix now
but i dont want to go there again this solution is much more simple

So we create a class called CharacterSelector
This class will hold a list of all the prefabs (Models) you want in my case it was 3 later i will put more
it will have a index for current character
a GameObject cached var for the currentModel
a Cached for the animator that sits on the player

What we will do here is in Awake we will Bring first the Animator Component for not having null errors.
we will already Apply the current character
Which in my case is the default model because this is how i want the people see the game
What this Method will do is , If a current model exist it will destroy it first
and then Create a new one and store it in the currentModel var
Then for fix the Animation will start a Corutine that what it does is basically reset the Animator off and on

Then what we will Save in Capture state will be currentCharacter Index which Get Set by the Character Panel Buttons .
Then We will Restore State the currentcharacter Index and apply the current Character which will do what we talk above . Destroy and make a new model reset animator

I hope everyone still understand if not , dont be shy to reply :]
i had a long few days about this

Btw from what you understand from this In the player prefab that is it you wont need a model anymore ! :]
it will be created from the list we put in this class so fun

public class CharacterSelector : MonoBehaviour, ISaveable
{
    [SerializeField] List<GameObject> models = new List<GameObject>();
    int currentCharacter = 0;
    GameObject currentModel;
    Animator animator;

    void Awake()
    {
        animator = GetComponent<Animator>();
        ApplyCurrentCharacter(); //default to character 0 until set or restoreState
    }

    public void SetCurrentCharacter(int character)
    {
        currentCharacter = character;
        ApplyCurrentCharacter();
    }

    void ApplyCurrentCharacter()
    {
       if (currentModel) Destroy(currentModel);
       currentModel = Instantiate(models[currentCharacter],transform);
       StartCoroutine(ResetAnimator());
    }

    IEnumerator ResetAnimator()
    {
       animator.enabled = false;
       currentModel.SetActive(false);
       yield return new WaitForSeconds(0.3f);
       animator.enabled = true;  
       currentModel.SetActive(true);
       animator.Rebind();
    }

    public object CaptureState()
    {
        return currentCharacter;
    }

    public void RestoreState(object state)
    {
        currentCharacter = (int)state;
        ApplyCurrentCharacter();
     }
}

So Back to the Character panel
We have there the Buttons they will call the CharacterSelector.SetCurrentCharacter and set the number between 1 - 3 in my case

Now Remember we had that Code that i did there A comment and said we will get back to it for Continue a new Game before that we need to explain what happen when you press Start on the button
i promise we will get there it is also very simple

So to make the Start and Load a new Game and save for the first time

First we will need to change that from now on from this scene On the PersistentObjectSpawner will be here and not on the Core Prefab as a different object
i believe everyone know what i talk about let me know in reply if need explain about this

we will need also to Create an Object called SceneLoader
in this object will be another class called SceneLoader
It will have inside ref for saveMenu
Fade times in out and wait time
Basically we are doing here same like we did with the portal
just a few minor changes
so if you understand the portal class you will understand this for sure

so this object is DontDestroyOnLoad then when it finish everything it gets destroy same like the portal
it calls the playerController disable it
then fade out

Set the slot Index which we will need to add in the Saving Wrapper ( Later i will share this too )
And after we set the slot Index for the saving wrapper we save a new file under the slot index which we get from the ref in the Save Menu !

Then we load the first Scene of the game Sandbox for RPG courses
We load the save from the slotIndex
We disable the new PlayerController from the scene of the sandbox
so we have the player controller from the scene CharacterSelection and the Sandbox

then we get the Starting position from the player Controller
Just add in the player Controller a new var of Vector3 startPos and in awake save the transfrom.position
Because the player was saved in the scene before and not spawn from the portal
we need to move the player
so we use the navmesh to warp to the start position dont forgot all of this the Player playing game cant see because we fade Out

then we Fade back in bring back Control
Save again and destroy the Object

public class SceneLoader : MonoBehaviour
{
    [SerializeField] SaveMenu saveMenu;
    [SerializeField] float fadeOutTime = 1f;
    [SerializeField] float fadeInTime = 2f;
    [SerializeField] float fadeWaitTime = 0.5f;
    [SerializeField] int sceneToLoad = 2;

    SavingWrapper savingWrapper;
    Fader fader;
    // Start is called before the first frame update
    void Awake()
    {
        savingWrapper = FindObjectOfType<SavingWrapper>();
        fader = FindObjectOfType<Fader>();
        saveMenu = saveMenu.GetComponent<SaveMenu>();
    }

    public void StartNewGame()
    {
        StartCoroutine(LoadNewGame());
    }

    IEnumerator LoadNewGame()
    {
        DontDestroyOnLoad(transform.root.gameObject);
        PlayerController playerController = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
        playerController.enabled = false;
        //Remove control player

        yield return fader.FadeOut(fadeOutTime);

        savingWrapper.SetSlotIndex(saveMenu.GetSlotIndex());
        savingWrapper.NewSaveFile(saveMenu.GetSlotIndex());
        
        yield return SceneManager.LoadSceneAsync(sceneToLoad);
        savingWrapper.LoadFromMenu(saveMenu.GetSlotIndex());
        PlayerController newPlayerController = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
        newPlayerController.enabled = false;
        //Change Player Character
        Vector3 startPos = newPlayerController.GetStartPos();
        newPlayerController.GetComponent<NavMeshAgent>().Warp(startPos);
        yield return new WaitForSeconds(fadeWaitTime);
        fader.FadeIn(fadeInTime);
        newPlayerController.enabled = true;
        savingWrapper.SetSlotIndex(saveMenu.GetSlotIndex());
        savingWrapper.NewSaveFile(saveMenu.GetSlotIndex());
        Destroy(gameObject); 
    }
}

This need to be added to the SavingSystem Script

public bool FileExists(string saveFile)
        {
            string path = GetPathFromSaveFile(saveFile);
            return File.Exists(path);
        }

Updated Saving Wrapper for the SlotIndex
Have some Debug probably some places feel free to delete Add etc

public class SavingWrapper : MonoBehaviour

    {

        const string defaultSaveFile = "Autosave";

        const string newSaveFile = "SaveSlot";

        [SerializeField] float fadeInTime = 0.2f;

        [SerializeField] float fadeOutTime = 1f;

        int saveSlotIndex = 0;

        IEnumerator LoadLastScene()

        {

            Debug.Log("LoadingLastScene");

            Debug.Log("Save Slot index is : " + saveSlotIndex);

            Fader fader = FindObjectOfType<Fader>();

            yield return fader.FadeOut(fadeOutTime);

            yield return GetComponent<SavingSystem>().LoadLastScene(newSaveFile + saveSlotIndex);

            yield return fader.FadeIn(fadeInTime);

        }

        // Update is called once per frame

        void Update()

        {

            if (Input.GetKeyDown(KeyCode.L))

            {

                Load();

            }

            if (Input.GetKeyDown(KeyCode.S))

            {

                Save();

            }

            if (Input.GetKeyDown(KeyCode.D))

            {

                Delete();

            }

        }

        public void SetSlotIndex(int index)

        {

            saveSlotIndex = index;

        }

        public void Delete()

        {

            GetComponent<SavingSystem>().Delete(newSaveFile + saveSlotIndex);

        }

        public void Load()

        {

            //Call to saving system to load

            GetComponent<SavingSystem>().Load(newSaveFile + saveSlotIndex);            

        }

        public void Save()

        {

            //Call to saving system to save

            GetComponent<SavingSystem>().Save(newSaveFile + saveSlotIndex);

        }

        public void NewSaveFile(int index)

        {

            GetComponent<SavingSystem>().Save(newSaveFile + index);

        }

        public void LoadFromMenu(int index)

        {

           GetComponent<SavingSystem>().Load(newSaveFile + index); 

        }

        public void LoadLastSave()

        {

            StartCoroutine(LoadLastScene());

        }

        public bool FileExists(int index)

        {

            return GetComponent<SavingSystem>().FileExists(newSaveFile + index);

        }

    }

And i know in the end i promised you all the Continue/Resume the save
So …

In the save Menu Script i told you all that this code will resume your LastSave
as you all see we Set the slot Index then use the new Method in Saving Wrapper of LoadLastSave
Its all the same like LoadLastScene just upgraded with fade out fade in properly

 if (savingWrapper.FileExists(index))
        {
            savingWrapper.SetSlotIndex(index);
            savingWrapper.LoadLastSave();
            gameObject.SetActive(false);
            return;
        }

So to Make the text appear in the Continue instead of SaveSlot 1 -3 i did it like this
very simple have an array of textmesh just go on them check if the file exist if it does write continue if not write the saveslot(1-3)

public class SaveMenu : MonoBehaviour
{
    [SerializeField] GameObject characterPanel;
    [SerializeField] GameObject backButton;
    [SerializeField] GameObject startButton;
    [SerializeField] Transform player;
    [SerializeField] TextMeshProUGUI [] savefilesNames;

    int slotIndex = 1;
    const string savefileName = "SaveSlot";
    SavingWrapper savingWrapper;

    private void Awake() 
    {
        savingWrapper = FindObjectOfType<SavingWrapper>();
    }

    private void Start() 
    {
        for (int i = 0; i < 3; i++)
        {
            if (savingWrapper.FileExists(i+1))
            {
                savefilesNames[i].text = "Continue";
            }
            else
            {
                savefilesNames[i].text = savefileName + (i+ 1);
            }
        }
    }

Some Photos can help with building the UI

Character Button

SaveSlot Button

SavePanel

Heirchy of the Scene of CharacterSelection
Unity_HznBhiIltr

1 Like

There Is something i forgot to write in the reply before

This Script will sit in each prefab/Model you will put in the List of models in CharacterSelector
So you attach it on the Prefab of the model
Like a Mage a Orc etc

public class ModelBone : MonoBehaviour
{
    [SerializeField] Transform leftHand;
    [SerializeField] Transform rightHand;

    Fighter player;

    private void Awake()
    {
        player = GameObject.FindWithTag("Player").GetComponent<Fighter>();

    }
    private void OnEnable()
    {
        player.SetHandTransfroms(rightHand, leftHand);
        player.GetComponent<Caster>().SetHandTransfroms(leftHand);
    }

}

Also right now there is a bug with Weapon Spawn in fighter after Continue LastSave
I will fix it and post later a fix

Bug Fix for Weapon Spawn Because of the ModelBone Script being called at certain time
So in the Fighter that the ModelBone Call for SetHandTransforms for switching the hands According to the new Model

This Code Should be Added to the Fighter With also an Update in the Update Weapon Look Down for another Piece of code

public void SetHandTransfroms(Transform right, Transform left)
        {
            rightHandTransform = right;
            leftHandTransform = left;
            UpdateWeapon();
        }

So the UpdateWeapon is Checking first if Equipment Exist then if it is it will respawn the sword when switching the transforms

public void UpdateWeapon()
        {
            if (!equipment) return;
            var weapon = equipment.GetItemInSlot(EquipLocation.Weapon) as WeaponConfig;
            if (weapon == null)
            {
                EquipWeapon(defaultWeapon);
            }
            else
            {
                EquipWeapon(weapon);
            }
        
        }
1 Like