1

In my scenario, I have a table (plane) that a ball will roll around on using nothing but physics giving the illusion that the mobile device is the table using Input.gyro.attitude. Taking it one step further, I would like this relative to the device origin at the time Start() is called, so if it is not being held in front of a face or flat on the table, but just relative to where it started, and may even be reset when the ball is reset. So the question is, is how do I get the difference between the current attitude and the origin attitude, then convert the X and Z(?) difference into a Vector3 to AddForce() to my ball object whilst capping the max rotation at about 30 degrees? I've looked into a lot of Gyro based input manager scripts and nothing really helps me understand the mystery of Quaternions.

I could use the relative rotation to rotate the table itself, but then I am dealing with the problem of rotating the camera along the same rotation, but also following the ball at a relative height but now with a tilted offset.

AddForce() works well for my purposes with Input.GetAxis in the Editor, just trying to transition it to the device without using a Joystick style UI controller.

Edit: The following code is working, but I don't have the right angles/euler to give the right direction. The game is played in Landscape Left/Right only, so I should only need a pitch and yaw axis (imagine the phone flat on a table), but not roll (rotated around the camera/screen). I may eventually answer my own question through trial and error, which I am sure is what most programmers do.... XD

Started on the right track through this answer: Answer 434096

private Gyroscope m_Gyro;
private speedForce = 3.0f;
private Rigidbody rb;

private void Start() {
    m_Gyro = Input.gyro;
    m_Gyro.enabled = true;
    rb = GetComponent<Rigidbody>();
}

private Vector3 GetGyroForces() {
    Vector3 resultantForce = Vector3.zero;

    //Quaternion deviceRotation = new Quaternion(0.5f, 0.5f, -0.5f, -0.5f) * m_Gyro.attitude * new Quaternion(0,1,0,0);

    float xForce = GetAngleByDeviceAxis(Vector3.up);
    float zForce = GetAngleByDeviceAxis(Vector3.right);
    //float zForce = diffRot.z;

    resultantForce = new Vector3(xForce, 0, zForce);

    return resultantForce;
}

private float GetAngleByDeviceAxis(Vector3 axis) {
    Quaternion currentRotation = m_Gyro.attitude;
    Quaternion eliminationOfOthers = Quaternion.Inverse(Quaternion.FromToRotation(axis, currentRotation * axis));

    Vector3 filteredEuler = (eliminationOfOthers * currentRotation).eulerAngles;

    float result = filteredEuler.z;
    if (axis == Vector3.up) {
        result = filteredEuler.y;
    }
    if (axis == Vector3.right) {
        result = (filteredEuler.y > 90 && filteredEuler.y < 270) ? 180 - filteredEuler.x : filteredEuler.x;
    }

    return result;
}

void FixedUpdate() {
#if UNITY_EDITOR
    rb.AddForce(new Vector3(Input.GetHorizontal * speedForce, 0, Input.GetVertical * speedForce));
#endif

#if UNITY_ANDROID
    rb.AddForce(GetGyroForces);
#endif
}
Karl
  • 25
  • 6

0 Answers0