Problem Recalling Player Position

Hi guys,

I’m having an issue that I’m hoping someone might be able to shed some light on.

In my game, I use the following system to save and recall the player’s position in the world when they exit and return to the game (it’s on iOS). The game is grid-based so the player moves in set squares around the game world.

The following variables exist in a script that is preserved throughout the lifetime of the game:

static var playerPositionX : float = 0.0;
static var playerPositionY : float = 0.0;
static var playerPositionZ : float = 0.0;
static var playerRotationX : float = 0.0;
static var playerRotationY : float = 0.0;
static var playerRotationZ : float = 0.0;
static var playerRotationW : float = 0.0;
static var playerFacing : int = 0;

When the player moves, the following code executes to set those variables:

persistence_ref.playerPositionX = gameObject.transform.localPosition.x;
persistence_ref.playerPositionY = gameObject.transform.localPosition.y;
persistence_ref.playerPositionZ = gameObject.transform.localPosition.z;
persistence_ref.playerRotationX = gameObject.transform.localRotation.x;
persistence_ref.playerRotationY = gameObject.transform.localRotation.y;
persistence_ref.playerRotationZ = gameObject.transform.localRotation.z;
persistence_ref.playerRotationW = gameObject.transform.localRotation.w;
persistence_ref.playerFacing = facing;

When a significant event occurs (e.g. find item, open door, change the world in some way), then the following code executes to save the player’s position:

PlayerPrefs.SetFloat("playerPositionX", playerPositionX);
PlayerPrefs.SetFloat("playerPositionY", playerPositionY);
PlayerPrefs.SetFloat("playerPositionZ", playerPositionZ);
PlayerPrefs.SetFloat("playerRotationX", playerRotationX);
PlayerPrefs.SetFloat("playerRotationY", playerRotationY);
PlayerPrefs.SetFloat("playerRotationZ", playerRotationZ);
PlayerPrefs.SetFloat("playerRotationW", playerRotationW);
PlayerPrefs.SetInt("playerFacing", playerFacing);

When the game launches, and the player “Continues” (rather than starting a new game), their current level is loaded up, and the following two chunks of code are executed in order:

playerPositionX = PlayerPrefs.GetFloat("playerPositionX", 0.0);
playerPositionY = PlayerPrefs.GetFloat("playerPositionY", 0.0);
playerPositionZ = PlayerPrefs.GetFloat("playerPositionZ", 0.0);
playerRotationX = PlayerPrefs.GetFloat("playerRotationX", 0.0);
playerRotationY = PlayerPrefs.GetFloat("playerRotationY", 0.0);
playerRotationZ = PlayerPrefs.GetFloat("playerRotationZ", 0.0);
playerRotationW = PlayerPrefs.GetFloat("playerRotationW", 0.0);
playerFacing = PlayerPrefs.GetInt("playerFacing", 0);
gameObject.transform.localPosition = Vector3(persistence_ref.playerPositionX, persistence_ref.playerPositionY, persistence_ref.playerPositionZ);
gameObject.transform.localRotation = Quaternion(persistence_ref.playerRotationX, persistence_ref.playerRotationY, persistence_ref.playerRotationZ, persistence_ref.playerRotationW);
facing = persistence_ref.playerFacing;

That’s it.

Now, this works perfectly 95% of the time, but here’s the problem:

About 5% of the time, the player (me at the moment) finds themself in a seemingly random location on the level. I’ve been over the logic of it a bunch of times, and I can’t see anything that could cause this to fail - i.e. as far as I can see, it should always work.

I’m hoping someone might just throw an idea at me that I haven’t tried. I’m pretty baffled by it at this point.

the coding look ok to me…

maybe you can try change localPosition to position?

About 5% of the time, the player (me at the moment) finds themself in a seemingly random location on the level?
can provide with more detail of it like wrong position/wrong rotation and so on…

I think in this case localPosition and position are interchangeable as the player object has no parent object. I’ve tried both though and the problem seems to exist in either case. I’ve just put “position” and “rotation” back in place (rather than localPosition and localRotation) and I’m going to do another play through to try and reproduce the problem.

I believe the rotation is generally correct, and it’s just the position that gets “lost”. I’ll confirm that also though.

OK. position/rotation vs. localPosition/localRotation definitely makes no difference in this case.

I just managed to reproduce the problem with the following debug log in place:

Debug.Log(gameObject.transform.position.x + "," + gameObject.transform.position.y + "," + gameObject.transform.position.z + "     " + gameObject.transform.rotation.x + "," + gameObject.transform.rotation.y + "," + gameObject.transform.rotation.z + "," + gameObject.transform.rotation.w);

So on most tests of (1) Start game, (2) Move around, (3) Exit game, (4) Continue game - the last two debug lines have the same numbers, and the player “Continues” in the correct place.

Here’s what the numbers look like though when the problem occurs:

Unboxed is last position before exiting game. Boxed is the position applied on continuing.

So I guess the question is: Where the hell is it getting those numbers from?!

Are your logs right after you save the values and after you get the values? If not I would put logs right before I save them, and put another log as soon as I get them. Also, if you can verify the values that are written out to file are matching what they should be. I almost want to guess that something else is possibly fooling with the positions either just before you save them out, or right after you load them in.

Also, I read in one post about PlayerPrefsX which had a link to here: http://www.unifycommunity.com/wiki/index.php?title=ArrayPrefs2

I’ve been trying out ArrayPrefs2 and PlayerPrefsX (using eulerAngles). Getting the same problems though. Bizarre.