Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Resolved Can Change Object Rotation But Not Position?

Discussion in 'Scripting' started by StephCat, Jul 13, 2020.

  1. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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:
    Code (CSharp):
    1. [System.Serializable]
    2. //structure of players data
    3. public class PlayerData
    4. {
    5.     public float PosX { get; set; }
    6.     public float PosY { get; set; }
    7.     public float PosZ { get; set; }
    8.     public float QuatX { get; set; }
    9.     public float QuatY { get; set; }
    10.     public float QuatZ { get; set; }
    11.     public float QuatW { get; set; }
    12.     public PlayerData(Vector3 position, Quaternion quat)
    13.     {
    14.         this.PosX = position.x;
    15.         this.PosY = position.y;
    16.         this.PosZ = position.z;
    17.         this.QuatX = quat.x;
    18.         this.QuatY = quat.y;
    19.         this.QuatZ = quat.z;
    20.         this.QuatW = quat.w;
    21.     }
    22. }

    and use these functions to save/load it (i have the file writing down fine so I won't include that)
    Code (CSharp):
    1.     private void SavePlayer(SaveData data)
    2.     {
    3.         Transform playerPosition = GameObject.Find("Player").transform;
    4.  
    5.         data.ThePlayerData = new PlayerData(playerPosition.position, playerPosition.rotation);
    6.     }
    7.  
    8.     private void LoadPlayer(SaveData data)
    9.     {
    10.         playerPosition.position = new Vector3(data.ThePlayerData.PosX, data.ThePlayerData.PosY, data.ThePlayerData.PosZ);
    11.         playerPosition.rotation = new Quaternion(data.ThePlayerData.QuatX, data.ThePlayerData.QuatY, data.ThePlayerData.QuatZ, data.ThePlayerData.QuatW);
    12.     }
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    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"
     
  3. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    Code (CSharp):
    1.  
    2.  
    3. //Save data should be serializable
    4. [System.Serializable]
    5. public class SaveData
    6. {
    7.     public PlayerData ThePlayerData { get; set; }
    8.  
    9.     //constructor to instantiate everything
    10.     public SaveData()
    11.     {
    12.     }
    13. }
    14.  
    15. [System.Serializable]
    16. //structure of players data
    17. public class PlayerData
    18. {
    19.     public float PosX { get; set; }
    20.     public float PosY { get; set; }
    21.     public float PosZ { get; set; }
    22.     public float QuatX { get; set; }
    23.     public float QuatY { get; set; }
    24.     public float QuatZ { get; set; }
    25.     public float QuatW { get; set; }
    26.     public PlayerData(Vector3 position, Quaternion quat)
    27.     {
    28.         this.PosX = position.x;
    29.         this.PosY = position.y;
    30.         this.PosZ = position.z;
    31.         this.QuatX = quat.x;
    32.         this.QuatY = quat.y;
    33.         this.QuatZ = quat.z;
    34.         this.QuatW = quat.w;
    35.     }
    36. }
    Code (CSharp):
    1.  
    2.  
    3. public class SaveManager : MonoBehaviour
    4. {
    5.     // Start is called before the first frame update
    6.     void Start()
    7.     {
    8.         //if you want to see where this persistent data path is on your computer
    9.         //Debug.Log(Application.persistentDataPath);  
    10.     }
    11.  
    12.     // Update is called once per frame
    13.     void Update()
    14.     {
    15.         if (Input.GetKeyDown(KeyCode.Q))
    16.         {
    17.             Save();
    18.         }
    19.         if(Input.GetKeyDown(KeyCode.E))
    20.         {
    21.             Load();
    22.         }
    23.     }
    24.  
    25.     private void Save()
    26.     {
    27.         try
    28.         {
    29.             BinaryFormatter formatter = new BinaryFormatter();
    30.  
    31.             //if the file is not there, we are going to create it. Creates file on harddrive
    32.             FileStream file = File.Open(Application.persistentDataPath + "/" + "SaveTest.dat", FileMode.Create);
    33.  
    34.             SaveData data = new SaveData();
    35.  
    36.             SavePlayer(data);
    37.  
    38.             formatter.Serialize(file, data);
    39.  
    40.             //need to close file or else there will be issues
    41.             file.Close();
    42.         }
    43.         catch (System.Exception) //catch exceptions so unity doesn't crash
    44.         {
    45.             //This will delete dave data if corrupted
    46.         }
    47.     }
    48.  
    49.     private void Load()
    50.     {
    51.         try
    52.         {
    53.             BinaryFormatter formatter = new BinaryFormatter();
    54.  
    55.             //if the file is not there, we are going to create it. Creates file on harddrive
    56.             FileStream file = File.Open(Application.persistentDataPath + "/" + "SaveTest.dat", FileMode.Open);
    57.  
    58.             SaveData data = (SaveData)formatter.Deserialize(file);
    59.  
    60.             //need to close file or else there will be issues
    61.             file.Close();
    62.  
    63.             LoadPlayer(data);
    64.         }
    65.         catch (System.Exception) //catch exceptions so unity doesn't crash
    66.         {
    67.             //This will delete dave data if corrupted
    68.         }
    69.     }
    70.  
    71.  
    72.     private void SavePlayer(SaveData data)
    73.     {
    74.         Transform playerPosition = GameObject.Find("Player").transform;
    75.  
    76. //i have tried combos of position, local position, setting vector 3 to zero... nothing changes the actual position in the game
    77.         data.ThePlayerData = new PlayerData(playerPosition.localPosition, playerPosition.rotation);
    78.     }
    79.  
    80.     private void LoadPlayer(SaveData data)
    81.     {
    82.         Transform playerPosition = GameObject.Find("Player").transform;
    83.  
    84.         playerPosition.localPosition = new Vector3(data.ThePlayerData.PosX, data.ThePlayerData.PosY, data.ThePlayerData.PosZ);
    85.         playerPosition.rotation = new Quaternion(data.ThePlayerData.QuatX, data.ThePlayerData.QuatY, data.ThePlayerData.QuatZ, data.ThePlayerData.QuatW);
    86.     }
    87. }
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    Thanks for sharing that. I know you said you were able to get rotation to work... But my current guess is that this property:
    Code (CSharp):
    1. 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.
     
  5. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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
    Code (CSharp):
    1.         Debug.Log("Position Saved: " + data.ThePlayerData.PosX + ", " + data.ThePlayerData.PosY + ", " + data.ThePlayerData.PosZ);
    2.         Debug.Log("Current Player Position: " + playerPosition.localPosition);
    3.         playerPosition.localPosition = new Vector3(data.ThePlayerData.PosX, data.ThePlayerData.PosY, data.ThePlayerData.PosZ);
    4.         Debug.Log("Current Player Position Has Changed To: " + playerPosition.localPosition);
    5.         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
    upload_2020-7-12_22-18-53.png
    I've also tried making ThePlayerData just "public PlayerData ThePlayerData;" but that doesn't seem to change anything
     
  6. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    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".
     
  7. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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
     
  8. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    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?
     
  9. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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
     
  10. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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?
     
  11. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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
     
  12. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    Clearly some other script is messing with your player's position. Do any of your other scripts move your player?
     
  13. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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.
     
    Last edited: Jul 13, 2020
  14. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    Disable everything except the save/load script. It should work. Enable things one by one to see what breaks it again.
     
  15. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    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)