Inventory and SavableEntity problem

Hi, I’m implementing your inventory course on my game and I’m running into some problems. I create some inventory items, but when I open the inventory they didn’t load in. The saving system also didn’t seem to work. When I load the game, the unique identifier on my player didn’t change at all, it was still “player”.

If the player’s SaveableEntity is set to player, it should stay that way. That’s actually normal.

Are you saying that when you save the game with items in the inventory then when the game reloads the items are gone?

I thought when the game is loaded, the “player” will be serialized into a random ID. In the video, when you created 2 items with the scriptable objects, they would be added to the inventory and shown in the inventory slots. I created 2 items but they didn’t show in the inventory slot. And about the saving system, when I walk around and save the game, but when I load the game it didn’t load the last player location where I saved the game

If we serialized the player into a random id, then we wouldn’t have a hook to save data between scenes specific to the player. We only want the enemies to have random ids.

At this point in the course, the inventory items that you see in the inventory were added in Awake() expliclty via their GUID (see the previous lecture Item ID explained.

Make sure at this point in the course that you are working off of the projects provided with each section, and not integrating into your own game until the final section where we use Inventory.zip.

I’m a bit confused because in the “Inventory Backing Store” scene when play the scene I saw in the hierarchy the unique identifier of the player turned into a random serial ID. Sorry about the idiotic question about the inventory items, I totally miss that part in the awake. I still don’t know why the loading and saving don’t work, maybe is it because of the capture state and restore state in my mover script? I removed the navmeshagent.enable since I’m not using it in 2D, I also didn’t use the ActionScheduler. And since I’m using RidgidBody2d instead of Transform, is that what causes the problem? Do I need to SerializeField the RidgidBody2d?

All GameObjects have a transform, whether they are 2D or 3D. Being a 2D game deals with how that transform is interpreted by the camera and the 2D physics system.

If the player is turning to a random serial ID, then the saving system won’t work as intended… I’m not sure why it would be doing that.

Paste in your version of the Mover script and we’ll take a look at what’s going on.

This is my PlayerController script:

using System.Collections;
using RPG.Saving;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{

    public Rigidbody2D myRigidBody2D;
    public float moveSpeed;
    public Animator myAnim;
    public static PlayerController instance;
    public string areaTransitionName;
    private Vector3 bottomLeftLimit;
    private Vector3 topRightLimit;
    public bool canMove = true;

    void Start()
    {

        if (instance == null)
        {

            instance = this;

        }
        else
        {

            if (instance != this)
            {

                Destroy(gameObject);

            }

        }

        DontDestroyOnLoad(gameObject);

    }

    // Update is called once per frame
    void Update()
    {
        if (!canMove)
        {
            myRigidBody2D.velocity = Vector2.zero;
            return;
        }

        myRigidBody2D.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * moveSpeed;

        myAnim.SetFloat("moveX", myRigidBody2D.velocity.x);
        myAnim.SetFloat("moveY", myRigidBody2D.velocity.y);

        if (Input.GetAxisRaw("Horizontal") == 1 || Input.GetAxisRaw("Horizontal") == -1 || Input.GetAxisRaw("Vertical") == -1 || Input.GetAxisRaw("Vertical") == 1)
        {

            myAnim.SetFloat("lastMoveX", Input.GetAxisRaw("Horizontal"));
            myAnim.SetFloat("lastMoveY", Input.GetAxisRaw("Vertical"));

        }

        transform.position = new Vector3(Mathf.Clamp(transform.position.x, bottomLeftLimit.x, topRightLimit.x), Mathf.Clamp(transform.position.y, bottomLeftLimit.y, topRightLimit.y), transform.position.z);

    }

    public void SetBounds(Vector3 botLeft, Vector3 topRight)
    {

        bottomLeftLimit = botLeft + new Vector3(0.5f, 0.5f, 0f);
        topRightLimit = topRight + new Vector3(-0.5f, -0.5f, 0f);

    }
    public object CaptureState()
    {
        return new SerializableVector3(transform.position);
    }

    public void RestoreState(object state)
    {
        SerializableVector3 position = (SerializableVector3)state;
        transform.position = position.ToVector();
    }

}

demo
This picture is from your Inventory Backing Store scene

I think for this section, they weren’t really worrying about it. Once it’s set, it shouldn’t change, even if it’s a random GUID. For game play, you want the ID for the player to be “player” in each scene, so that the player in each scene can access all the information.

And is there anything wrong with my playercontroller script?

In terms of the saving system, no.

The script is set up as a Singleton, which may be causing your issue with the player not saving/restoring properly.
When a GameObject is made into a Singleton, it is placed in a special scene that is technically separate from the main scene. You can see this in the inspector during game play, the player will be moved from the main heirarchy into the DontDestroyOnLoad heirarchy.
When the Saving System restores, it will find any other GameObjects in the scene that was just loaded and act on them first, then find the ones that are in the DontDestroyOnLoad… this is nothing you can change, it’s part of how the FindObjectsOfType and FindWithTag methods work.
The Inventory system finds the player’s UI by locating the player by the Tag. If you have a player in each scene and one is destroyed via the Singleton method, the Inventory will find the first instance (in the scene file), but then that player is destroyed by the Singularity, and the inventory system has a link to a destroyed GameObject.
At the very least, the Singleton code needs to be placed in the Awake() method. In a typical save on loading a scene or moving between scenes, the Saving system acts immediately after Awake(), but before Start().

A better solution is to not make the player a Singleton, but keeping an identical copy of the player prefab (make edits to the prefab, not the player in the scene file, and everything should should stay the same!). When the scene is loaded, the system will find the new player and restore it’s condition appropriately.

This concept is explored in further detail in the RPG: Core Combat course.

that problem that I’m having, Singleton. I’m pretty new to the whole game development, I was studying another course in Udemy but the more I get into that I realize a huge problem with that course is they have a lot of singleton patterns. That is why I study some of GameDev.TV course to fix this singleton problem. But still I’m pretty lost on finding the right source to learn about the basic concept like camera and movement in 2D which I think I very much different from 3D. Do you have any recommendation source on how can I improve the player-related script? That would be a big help

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

Privacy & Terms