Issue with rotation when transform.up is aligning to a direction

I am testing out some ideas in Unity where a player can walk around a circle while staying on it (so the circle has its own gravity) and also being oriented properly. This game is currently being done in 2D, so all objects are sprites, but the bug can be reproduced in 3D space.

I do hope I can explain myself properly. Please ask if you need any further clarification…

It appeared that I succeeded with my idea until I noticed something odd.

So as expected, the player moves around the circle without falling off (custom gravity worked just fine) and its Z rotation is affected as it aligns itself with a direction:

using UnityEngine;
using System.Collections;

public class TestOrient : MonoBehaviour {

    public GameObject planet;

    private void Update()
    {
        // We reverse the direction so the player points exactly away from the planet (to stand up)
        transform.up = -(planet.transform.position - transform.position);
    }
}

It works… mostly. However, when the player object’s rotation Z naturally reaches 180, it appears to flip horizontally (like a mirror effect) and then it returns to normal as rotation Z leaves 180. The visual flip happens because for some reason the object’s Y becomes 180 at the same time too. At no other point does X or Y change in regards to rotation. Only Z. So the moment Z hits 180, Y is affected and the moment we leave Z 180, Y returns to 0.

I’m happy to provide a quick video of it happening in-game if anybody needs some visual understanding of what’s going on.

The visibility of this bug tends to rely on how fast you’re moving around the circle. If you’re moving fast enough, you can probably skip over 180 and not see it happen at all, however if you move slow enough there’s no denying it’s there. It’s also problematic for the fact that I simply make the camera a child of the player so when the player flips, so does the camera causing the entire scene to flip which can look extremely glitchy for a player to see.

I really have no idea how to tackle this issue as I have no clue why it would do such a thing. At every other rotation value it behaves just fine. It’s only at Z = 180 (so the object is exactly upside down) does it decide to rotate in the wrong ways.


For those interested this is an easy way of reproducing the bug: That sample code up there is really all you need.

Just create a cube and a sphere, put both at position Z=0 (it helps make the bug happen but it’s not mandatory) add the orient script to the cube, drag the sphere as the planet in the inspector. Begin playing. Lock the cube in the inspector view as we’ll need to keep an eye on its rotation values. Begin moving the sphere slowly in the scene view so the cube’s rotation Z value begins moving towards 180. The tricky part is making it land exactly on 180, usually you’ll miss it and hit 179 or 181. Keep trying. The moment you hit 180, Y should change to 180 too. You will see with the local handle rotations that the cube’s blue arrow now points in the opposite direction and so does the red handle. The moment you move the sphere again and the value moves away from Z180, everything returns to normal.

You can try using: Unity - Scripting API: Quaternion.FromToRotation

Rotations should always be done with Quaternions, not directly modifying properties