About Respawning lesson and strange bug appears

Hello @sampattuzzi I came back after one month or so and I’ve seen a lot of update on the course, so I check all the lesson left white from before and I went little in confusion when I’ve seen you make a different section for the saving system and allow it as a separate download. I’d already pass all the course so I not import it and went to the other lessons until here. So I check the respawn stuff and the resource folder and the first error I got was about the namespace, I had Health class on the namespace Resources so I could not use your code, so, I not know if I did it right but I changed the namespace of health script as RPG.Core and did all this for all the scripts being called. Ok that’s one stuff, the other problem come up as long as I implement the saving system of the weapon and the respawn. I did a test just for fun of passing a portal without any weapon on hand and I got the error:

NullReferenceException: Object reference not set to an instance of an object
RPG.Combat.Fighter.CaptureState () (at Assets/Scripts/Combat/Fighter.cs:136)
RPG.Saving.SaveableEntity.CaptureState () (at Assets/Scripts/Saving/SaveableEntity.cs:28)
RPG.Saving.SavingSystem.CaptureState (System.Collections.Generic.Dictionary`2[TKey,TValue] state) (at Assets/Scripts/Saving/SavingSystem.cs:82)
RPG.Saving.SavingSystem.Save (System.String saveFile) (at Assets/Scripts/Saving/SavingSystem.cs:32)
RPG.SceneManagement.SavingWrapper.Save () (at Assets/Scripts/SceneManagement/SavingWrapper.cs:43)
RPG.SceneManagement.Portal+<Transition>d__8.MoveNext () (at Assets/Scripts/SceneManagement/Portal.cs:64)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)

the error apperas on this call in fighter.cs script during saving between portals

        public object CaptureState()
        {        
            return currentWeapon.name;
        }

Ok so I did little investigation on the Portal script and did little debug.log as follow:

 private IEnumerator Transition()
        {
         
            if (sceneToLoad < 0)
            {
                Debug.LogError("Scene to load not set !");
                yield break;
            }
  
            DontDestroyOnLoad(gameObject);

            Fader fader = FindObjectOfType<Fader>();
            SavingWrapper savingWrapper = FindObjectOfType<SavingWrapper>();
            yield return fader.FadeOut(fadeOutTime);
            //Before the saveing of Player position, I reset it to the spawn point of the portal for prevent infinite loop
            Debug.Log("before portal save");
            savingWrapper.Save();
            yield return SceneManager.LoadSceneAsync(sceneToLoad);
            Debug.Log("before portal load");
            savingWrapper.Load();
            Debug.Log("after portal load");
            Portal otherPortal = GetOtherPortal();
            UpdatePlayer(otherPortal);
            Debug.Log("before portal save again");
            //// HERE IS THE ISSUE
            savingWrapper.Save();
            Debug.Log("after portal save again");
            yield return new WaitForSeconds(fadeWaitTime);
            yield return fader.FadeIn(fadeInTime);
            GameObject.FindWithTag("Player").GetComponent<PlayerController>().enabled = true;
            Destroy(gameObject);
        }

I did not see the message after the portal save again, and I manage to solve it only by moving the last save instruction after the first yield return new WaitForSeconds(fadeWaitTime);
I suspect it has something to do with the weapons not loaded properly on the change of the scene or not initialized properly ?
If I stop execution of Unity after the crash and then reload the last scene it work properly even on the scene switch even without the fix but not understand really well why this happen and if only happen to me.
Last question is, why we never save the rotation ? in mover we saving only the position right ? But when reload the last checkpoint and player is facing another direction it’s look kinda weird.
Sorry for long question but I hope you could help me out. And maybe that this help someone others, and thank you for your amazing work.

There’s a lot of questions here. Could you summarise?

Well guess it’s a long question then, let’s just focus on the error part then. Why I got the error on CaptureState() when I’m using the weapon saving system while before the same code work ?

I’m not clear on what the before and after was. When was it working then what did you change?

Just a couple of additional questions.

  1. Do you have a weapon assigned at all when you go though the portal
  2. Is the weapon field empty when you go though the portal (If memory serves it should never be empty)

The error is saying that you havent got a weapon at the time of the crash so either its not assigned before going though the portal or its trying to save the weapon before its loaded the scene fully and it at that time has no weapon.

I wonder if this is one of the race conditions and it gets fixed later.

The question on rotation is choice, We dont really need to save the rotation for functionality and thats more of a polish and is quite simple to do, I believe Eddie has posted his solution to this in one of the Q&A posts on Udemy.

Hope this helps and hope you dont mind me jumping in Sam :slight_smile:

1 Like

Sorry to Sam for my bad explanation. As I said before, I jump in back into the RPG course after maybe 1 month and I found out that inside the course the structure was changed from before and a section regarding the saving system pop out as not completed. So I jump in and check it and found out that inside it you put an asset dedicated for the saving system.
I NOT applied it to my old project because it was working pretty well already but decide to redo the saving lesson.
After that I arrived to the weapon saving part and follow your instruction about the use of the Resources folder for saving the scriptable weapon object and here comes the first problem. I could not access the Resources because it said it’s already conflicting to the old namespace assigned to Health script.
I changed the Namespace of Health as RPG.Core and fix the first problem, after that I finish the lesson until the respawn weapon and the saving system work BEFORE passing a portal.
I did test BOTH the passage of the Player unarmed, and armed, and yet got the same error on the first passage of the portal the game freeze with the error reported.
I did the check with debug.log just for explain better all the test I did before write here and as said up it’s kinda like a race condition but not know why this happen to the player.
I double check more then once that all the enemy has weapons or is marked as unarmed as well as player too, my player start always unarmed on the first scene.
I did test same problem starting the game form the second scene, traveling to the first scene, it happen the same.
I did delete always the save file before making the test.
Sorry again if that’s not clear but I never know how to explain better then that actually …

----- EDIT WALL OF TEXT -------
I did some more testing, starting from my backup of the last time I finish the RPG course, I imported the saving asset and check the script, the only noticable difference is on the SavingSystem.cs where before I had this code:

public IEnumerator LoadLastScene(string saveFile)
        {
            Dictionary<string, object> state = LoadFile(saveFile);
            if (state.ContainsKey("lastSceneBuildIndex"))
            {
                int buildIndex = (int)state["lastSceneBuildIndex"];
                if (buildIndex != SceneManager.GetActiveScene().buildIndex)
                {
                    yield return SceneManager.LoadSceneAsync(buildIndex);
                }
            }        
            RestoreState(state);
        }

And now is like:

public IEnumerator LoadLastScene(string saveFile)
        {
            Dictionary<string, object> state = LoadFile(saveFile);
            int buildIndex = SceneManager.GetActiveScene().buildIndex;
            if (state.ContainsKey("lastSceneBuildIndex"))
            {
                buildIndex = (int)state["lastSceneBuildIndex"];
            }
            yield return SceneManager.LoadSceneAsync(buildIndex);
            RestoreState(state);
        }

Other then that no other changes at all, so I start again to make some testing and on the fighter.cs inside the CaptureState script I only add a null prevention like that:

 public object CaptureState()
        {
            if (currentWeapon == null) return "Unarmed";
            return currentWeapon.name;
        }

After I put that check and set back on the right position in the portal.cs the savingWrapper.Save(); now all works, all enemy has the right weapon as well as player while passing portals. If you want to check it better I could provide you the project to test it if that can help.

---- LAST UPDATE ON TESTING ----
Sorry for bother but I would just update you on the last testing results, with the version before all seems working well EXCEPT sometimes if you kill an enemy just after passing a portal. If you reload last savegame seems like the Enemy not get saved the weapon they were using ! So at the end seems really a question of race, I post here the final changes I did on the scripts on Portal.cs

 private IEnumerator Transition()
        {         
            if (sceneToLoad < 0)
            {
                Debug.LogError("Scene to load not set !");
                yield break;
            } 
            DontDestroyOnLoad(gameObject);
            Fader fader = FindObjectOfType<Fader>();
            SavingWrapper savingWrapper = FindObjectOfType<SavingWrapper>();
            yield return fader.FadeOut(fadeOutTime);
            savingWrapper.Save();
            yield return SceneManager.LoadSceneAsync(sceneToLoad);
            savingWrapper.Load();
            Portal otherPortal = GetOtherPortal();
            UpdatePlayer(otherPortal);
            yield return new WaitForSeconds(fadeWaitTime);
            savingWrapper.Save();
            yield return fader.FadeIn(fadeInTime);
            GameObject.FindWithTag("Player").GetComponent<PlayerController>().enabled = true;
            Destroy(gameObject);
        }

and Fighter.cs

 public object CaptureState()
        {
            if (currentWeapon == null) return "Unarmed";
            return currentWeapon.name;
        }

@sampattuzzi did this one get lost or solved?

Perhaps we could have a concise summary of the issue? We could also check out the project if you zipped it up or put it on Github

I would love to upload the bugged version but after a crash of my system I did not imported the backup of the bugged version anymore sadly. Anyway after progress on the course I see that lot changed after some refactoring and if no other complain about it you can close up the discussion here. I did try to show all the process and solution in all the other post, next time I will try to be more precise with a link to the project and a summarized post, my bad I noted it.

1 Like

Privacy & Terms