Can Change Object Rotation But Not Position?

Hello,

I’m trying to get a save/load system going and want to affect the player position and rotation on a load. The weird thing is that while I can get the player’s rotation to change successfully, I can’t get the position to and I don’t know why.

I save the data in this class:

[System.Serializable]
//structure of players data
public class PlayerData
{
    public float PosX { get; set; }
    public float PosY { get; set; }
    public float PosZ { get; set; }
    public float QuatX { get; set; }
    public float QuatY { get; set; }
    public float QuatZ { get; set; }
    public float QuatW { get; set; }
    public PlayerData(Vector3 position, Quaternion quat)
    {
        this.PosX = position.x;
        this.PosY = position.y;
        this.PosZ = position.z;
        this.QuatX = quat.x;
        this.QuatY = quat.y;
        this.QuatZ = quat.z;
        this.QuatW = quat.w;
    }
}

and use these functions to save/load it (i have the file writing down fine so I won’t include that)

    private void SavePlayer(SaveData data)
    {
        Transform playerPosition = GameObject.Find("Player").transform;

        data.ThePlayerData = new PlayerData(playerPosition.position, playerPosition.rotation);
    }

    private void LoadPlayer(SaveData data)
    {
        playerPosition.position = new Vector3(data.ThePlayerData.PosX, data.ThePlayerData.PosY, data.ThePlayerData.PosZ);
        playerPosition.rotation = new Quaternion(data.ThePlayerData.QuatX, data.ThePlayerData.QuatY, data.ThePlayerData.QuatZ, data.ThePlayerData.QuatW);
    }

I notice in SavePlayer playerPosition is a local variable that you are populating as you declare it on line 3 of your snippet. However in LoadPlayer you have a variable with the same name but the declaration and initialization of that variable are not in your snippet. This reads as fishy to me.

Can you share the rest of that script? I’m specifically interested in the declaration and initialization of “playerPosition”

//Save data should be serializable
[System.Serializable]
public class SaveData
{
    public PlayerData ThePlayerData { get; set; }

    //constructor to instantiate everything
    public SaveData()
    {
    }
}

[System.Serializable]
//structure of players data
public class PlayerData
{
    public float PosX { get; set; }
    public float PosY { get; set; }
    public float PosZ { get; set; }
    public float QuatX { get; set; }
    public float QuatY { get; set; }
    public float QuatZ { get; set; }
    public float QuatW { get; set; }
    public PlayerData(Vector3 position, Quaternion quat)
    {
        this.PosX = position.x;
        this.PosY = position.y;
        this.PosZ = position.z;
        this.QuatX = quat.x;
        this.QuatY = quat.y;
        this.QuatZ = quat.z;
        this.QuatW = quat.w;
    }
}
public class SaveManager : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //if you want to see where this persistent data path is on your computer
        //Debug.Log(Application.persistentDataPath);  
    }

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

    private void Save()
    {
        try
        {
            BinaryFormatter formatter = new BinaryFormatter();

            //if the file is not there, we are going to create it. Creates file on harddrive
            FileStream file = File.Open(Application.persistentDataPath + "/" + "SaveTest.dat", FileMode.Create);

            SaveData data = new SaveData();

            SavePlayer(data);

            formatter.Serialize(file, data);

            //need to close file or else there will be issues
            file.Close();
        }
        catch (System.Exception) //catch exceptions so unity doesn't crash
        {
            //This will delete dave data if corrupted
        }
    }

    private void Load()
    {
        try
        {
            BinaryFormatter formatter = new BinaryFormatter();

            //if the file is not there, we are going to create it. Creates file on harddrive
            FileStream file = File.Open(Application.persistentDataPath + "/" + "SaveTest.dat", FileMode.Open);

            SaveData data = (SaveData)formatter.Deserialize(file);

            //need to close file or else there will be issues
            file.Close();

            LoadPlayer(data);
        }
        catch (System.Exception) //catch exceptions so unity doesn't crash
        {
            //This will delete dave data if corrupted
        }
    }


    private void SavePlayer(SaveData data)
    {
        Transform playerPosition = GameObject.Find("Player").transform;

//i have tried combos of position, local position, setting vector 3 to zero... nothing changes the actual position in the game
        data.ThePlayerData = new PlayerData(playerPosition.localPosition, playerPosition.rotation);
    }

    private void LoadPlayer(SaveData data)
    {
        Transform playerPosition = GameObject.Find("Player").transform;

        playerPosition.localPosition = new Vector3(data.ThePlayerData.PosX, data.ThePlayerData.PosY, data.ThePlayerData.PosZ);
        playerPosition.rotation = new Quaternion(data.ThePlayerData.QuatX, data.ThePlayerData.QuatY, data.ThePlayerData.QuatZ, data.ThePlayerData.QuatW);
    }
}

Thanks for sharing that. I know you said you were able to get rotation to work… But my current guess is that this property:

public PlayerData ThePlayerData { get; set; }

Is not serializing at all. Does BinaryFormatter actually serialize properties at all? I know Unity doesn’t by default.

A couple things I would try:
First, Debug.Log the values of the SaveData/PlayerData objects right after loading. Then at least you can verify if it’s an issue with loading the data or if it’s an issue of just moving your player based on the loaded data.

If the data is actually not loading properly, try turning the ThePlayerData property into a plain old field.

So the data supposedly is loading properly. I put some debugs before and after trying to change the transform and this is what i get

        Debug.Log("Position Saved: " + data.ThePlayerData.PosX + ", " + data.ThePlayerData.PosY + ", " + data.ThePlayerData.PosZ);
        Debug.Log("Current Player Position: " + playerPosition.localPosition);
        playerPosition.localPosition = new Vector3(data.ThePlayerData.PosX, data.ThePlayerData.PosY, data.ThePlayerData.PosZ);
        Debug.Log("Current Player Position Has Changed To: " + playerPosition.localPosition);
        playerPosition.rotation = new Quaternion(data.ThePlayerData.QuatX, data.ThePlayerData.QuatY, data.ThePlayerData.QuatZ, data.ThePlayerData.QuatW);

but as you can see, clearly the position hasn’t changed at all. It’s still at -1.5, 0.1, -1,1. despite saying it’s been changed appropriately
6083907--660306--upload_2020-7-12_22-18-53.jpg
I’ve also tried making ThePlayerData just “public PlayerData ThePlayerData;” but that doesn’t seem to change anything

Are you 100% certain there’s only one GameObject named “Player” in the game when you load? Try searching in the scene hierarchy window for “Player”.

Sorry my post freaked out for a hot second and I just fixed it. There is a photo where you can see the “Player” game object is highlighted in the hierarchy, as well as the transform saying its been changed but it hasn’t

Oh wait I just noticed something. Your player object has an Animator on it. Can you try disabling the Animator temporarily and loading the data?

Setting the animator.enabled to false didn’t seem to change anything. I even left it disabled the whole time and i could still rotate, but no position change

I’ve just tested instantiating a cube at the coordinates I set and the cube spawns correctly. Maybe I can delete the player object and instantiate it in the new area?

So I can correctly instantiate a new “Player” into the scene at the position and rotation, however this breaks all the links to everything so this is not the optimum solution. I wish I knew why this is getting held up

Clearly some other script is messing with your player’s position. Do any of your other scripts move your player?

I’ve fixed it, but I have no idea why what I did worked. Basically, The object “Player” Was part of a “Game Essentials” prefab. Within the player parent object there was a child object that was an organizer for the player parts (graphics, cam, etc). I found with testing I could move that object, just not the top parent object. So I moved all the code and controller stuff that was on the parent object onto this child object, then moved the child out of the parent so it was it’s own thing. Now I can move it as expected.

Disable everything except the save/load script. It should work. Enable things one by one to see what breaks it again.

Thanks for your help all this time! I did some weird stuff and it fixed it somehow. I’m not going to question it haha (i changed my post talking about the player controller to just explain what I did to fix it)