Skip to main content
added 4708 characters in body
Source Link
Cato
  • 103
  • 1
  • 9

UPDATE:

Okay so I have made progress on this and have managed to achieve the above. Here is what I do:

Step 1: I read the gyroscope attitude and store it as a device rotation. The function I use is this:

private Quaternion GetDeviceRotation()
{
    if (SystemInfo.supportsGyroscope)
        return new Quaternion(0.5f, 0.5f, -0.5f, 0.5f) * Input.gyro.attitude * new Quaternion(0, 0, 1, 0);
}

I found this function here, whilst I am not entirely clear how it works, the author states "it is a wrapper for gyro input which adjusts the forward axis and takes different device orientations into account".

This gives me the current rotation of the device. I take this at the start of the game, or whenever I need to set the reference, and save it as the "ReferenceRotation".

Step 2: I then get the roll angle about the z-axis of the ReferenceRotation using this function:

private float GetRollAngle(Quaternion refRotation, Quaternion currentRotation)
{
    // Eliminate the XY planes whilst maintaining Z
    Quaternion eliminationOfXY = Quaternion.Inverse(Quaternion.FromToRotation(refRotation * Vector3.forward, currentRotation * Vector3.forward));

    // Deduce the z-axis roll angle
    Quaternion rotationZ = eliminationOfXY * currentRotation;
    return rotationZ.eulerAngles.z;
}

This function takes two quaternions and eliminates the XY axes. It then finds the roll about the z-axis. To get this angle for the ReferenceRotation, I pass it as both parameters in the signature.

Step 3: Now that I have a reference z-axis angle from which to measure tilt, I grab the real-time device rotation "CurrentRotation" in the Update() loop using the function in Step 1. I then compare this with the "ReferenceRotation" to get the current roll angle, using the function in Step 2. In this case, I pass ReferenceRotation and CurrentRotation respectively.

This then gives me the 'live' roll angle perfectly, without any issues.

I can point the device in front of me, set the reference, and tilt to see the correct roll angle change. At this referenced orientation, changing the pitch (x-axis) or yaw (y-axis) has no effect on the roll angle, which is exactly how it should be. If I then change the orientation of the device, i.e. point it up to the sky and reset the reference, the same behaviour is observed.

In effect, it works perfectly!


What then is the issue?

The issue is that I need to do the same thing for yaw about the y-axis (I found that rolling about z-axis was a bit awkward in terms of gameplay). By "yaw" I mean this motion:

enter image description here

For some reason, my method does not seem to work as well for yaw as it did for roll. Let's repeat the steps:

Step 1: As above

Step 2: Similar to the above, but instead I adjust the function to use Vector3.up instead, to correspond to the y-axis:

private float GetYawAngle(Quaternion refRotation, Quaternion currentRotation)
{
    // Eliminate the XZ planes whilst maintaining Y
    Quaternion eliminationOfXZ = Quaternion.Inverse(Quaternion.FromToRotation(refRotation * Vector3.up, currentRotation * Vector3.up));

    Quaternion yDifference = eliminationOfXZ * currentRotation;
    return yDifference.eulerAngles.y;

}

Step 3: As above

For some reason, this does not work and the measurement of the yaw angle goes completely haywire. After some experimentation, I found that if instead I pass Quaternion.Identity as the first parameter, during both function calls (i.e. Step 2 and 3), the method does actually work! I can accurately set the reference yaw angle and measure its change.

BUT in this case, changing the roll DOES affect the yaw angle. This is bad and I need to eliminate this problem. I need the same behaviour as the z-axis, i.e. movement in the other axes not to affect my axis of interest. So in this case, I do not want pitch or roll affecting my yaw reading.

My suspicions lead to me believe the issue boils down to the function in the very first step. The author mentioned how this function is "adjusted for the forward" axis, though I have no idea what that means as I struggle with Quaternions. Perhaps I need to re-adjust it for the up axis?

If anyone has any ideas, I would appreciate it tremendously. Apologies for the very long post, I hope it all made sense!


UPDATE:

Okay so I have made progress on this and have managed to achieve the above. Here is what I do:

Step 1: I read the gyroscope attitude and store it as a device rotation. The function I use is this:

private Quaternion GetDeviceRotation()
{
    if (SystemInfo.supportsGyroscope)
        return new Quaternion(0.5f, 0.5f, -0.5f, 0.5f) * Input.gyro.attitude * new Quaternion(0, 0, 1, 0);
}

I found this function here, whilst I am not entirely clear how it works, the author states "it is a wrapper for gyro input which adjusts the forward axis and takes different device orientations into account".

This gives me the current rotation of the device. I take this at the start of the game, or whenever I need to set the reference, and save it as the "ReferenceRotation".

Step 2: I then get the roll angle about the z-axis of the ReferenceRotation using this function:

private float GetRollAngle(Quaternion refRotation, Quaternion currentRotation)
{
    // Eliminate the XY planes whilst maintaining Z
    Quaternion eliminationOfXY = Quaternion.Inverse(Quaternion.FromToRotation(refRotation * Vector3.forward, currentRotation * Vector3.forward));

    // Deduce the z-axis roll angle
    Quaternion rotationZ = eliminationOfXY * currentRotation;
    return rotationZ.eulerAngles.z;
}

This function takes two quaternions and eliminates the XY axes. It then finds the roll about the z-axis. To get this angle for the ReferenceRotation, I pass it as both parameters in the signature.

Step 3: Now that I have a reference z-axis angle from which to measure tilt, I grab the real-time device rotation "CurrentRotation" in the Update() loop using the function in Step 1. I then compare this with the "ReferenceRotation" to get the current roll angle, using the function in Step 2. In this case, I pass ReferenceRotation and CurrentRotation respectively.

This then gives me the 'live' roll angle perfectly, without any issues.

I can point the device in front of me, set the reference, and tilt to see the correct roll angle change. At this referenced orientation, changing the pitch (x-axis) or yaw (y-axis) has no effect on the roll angle, which is exactly how it should be. If I then change the orientation of the device, i.e. point it up to the sky and reset the reference, the same behaviour is observed.

In effect, it works perfectly!


What then is the issue?

The issue is that I need to do the same thing for yaw about the y-axis (I found that rolling about z-axis was a bit awkward in terms of gameplay). By "yaw" I mean this motion:

enter image description here

For some reason, my method does not seem to work as well for yaw as it did for roll. Let's repeat the steps:

Step 1: As above

Step 2: Similar to the above, but instead I adjust the function to use Vector3.up instead, to correspond to the y-axis:

private float GetYawAngle(Quaternion refRotation, Quaternion currentRotation)
{
    // Eliminate the XZ planes whilst maintaining Y
    Quaternion eliminationOfXZ = Quaternion.Inverse(Quaternion.FromToRotation(refRotation * Vector3.up, currentRotation * Vector3.up));

    Quaternion yDifference = eliminationOfXZ * currentRotation;
    return yDifference.eulerAngles.y;

}

Step 3: As above

For some reason, this does not work and the measurement of the yaw angle goes completely haywire. After some experimentation, I found that if instead I pass Quaternion.Identity as the first parameter, during both function calls (i.e. Step 2 and 3), the method does actually work! I can accurately set the reference yaw angle and measure its change.

BUT in this case, changing the roll DOES affect the yaw angle. This is bad and I need to eliminate this problem. I need the same behaviour as the z-axis, i.e. movement in the other axes not to affect my axis of interest. So in this case, I do not want pitch or roll affecting my yaw reading.

My suspicions lead to me believe the issue boils down to the function in the very first step. The author mentioned how this function is "adjusted for the forward" axis, though I have no idea what that means as I struggle with Quaternions. Perhaps I need to re-adjust it for the up axis?

If anyone has any ideas, I would appreciate it tremendously. Apologies for the very long post, I hope it all made sense!

Mod Moved Comments To Chat
added 1 character in body
Source Link
Cato
  • 103
  • 1
  • 9

I am developing a Unity game where I need to tilt an iOS device to steer a ship as it flies in a straight line. The steering should be consistently accurate in any orientation, e.g. if the player holds the device directly in front of their face or if they are slouched over with the phone facing the ground etc. This is shown in the image below.

Phone upright, rolling to the right / Phone flat, yawing to the right

A summary of my needs are:

  • Tilt the device to alter the on-screen ship's rotation (one axis only - in Unity this is the object's y-axis since it is a top-down 3D game). This is why I say "tilt" (think Temple Run), panning around in space to change all axes is not necessary and needs to be prevented.
  • I need to know how quickly the user is tilting their device to control the steering speed
  • I need to know the current tilt angle at any instance
  • I need to enforce a maximum tilt angle (e.g. tilting beyond +/- 45 degree has no further effect on the ship)
  • I need smoothness and no jerkiness

Can someone with knowledge please advise me how to achieve this with the gyroscope in Unity? I have been experimenting with my phone using the Unity Remote app and playing around with the Input.gyro and Input.acceleration functions, but I cannot make sense of the angle data as the pitch and yawroll of the device changes.

I am developing a Unity game where I need to tilt an iOS device to steer a ship as it flies in a straight line. The steering should be consistently accurate in any orientation, e.g. if the player holds the device directly in front of their face or if they are slouched over with the phone facing the ground etc. This is shown in the image below.

Phone upright, rolling to the right / Phone flat, yawing to the right

A summary of my needs are:

  • Tilt the device to alter the on-screen ship's rotation (one axis only - in Unity this is the object's y-axis since it is a top-down 3D game). This is why I say "tilt" (think Temple Run), panning around in space to change all axes is not necessary and needs to be prevented.
  • I need to know how quickly the user is tilting their device to control the steering speed
  • I need to know the current tilt angle at any instance
  • I need to enforce a maximum tilt angle (e.g. tilting beyond +/- 45 degree has no further effect on the ship)
  • I need smoothness and no jerkiness

Can someone with knowledge please advise me how to achieve this with the gyroscope in Unity? I have been experimenting with my phone using the Unity Remote app and playing around with the Input.gyro and Input.acceleration functions, but I cannot make sense of the angle data as the pitch and yaw of the device changes.

I am developing a Unity game where I need to tilt an iOS device to steer a ship as it flies in a straight line. The steering should be consistently accurate in any orientation, e.g. if the player holds the device directly in front of their face or if they are slouched over with the phone facing the ground etc. This is shown in the image below.

Phone upright, rolling to the right / Phone flat, yawing to the right

A summary of my needs are:

  • Tilt the device to alter the on-screen ship's rotation (one axis only - in Unity this is the object's y-axis since it is a top-down 3D game). This is why I say "tilt" (think Temple Run), panning around in space to change all axes is not necessary and needs to be prevented.
  • I need to know how quickly the user is tilting their device to control the steering speed
  • I need to know the current tilt angle at any instance
  • I need to enforce a maximum tilt angle (e.g. tilting beyond +/- 45 degree has no further effect on the ship)
  • I need smoothness and no jerkiness

Can someone with knowledge please advise me how to achieve this with the gyroscope in Unity? I have been experimenting with my phone using the Unity Remote app and playing around with the Input.gyro and Input.acceleration functions, but I cannot make sense of the angle data as the pitch and roll of the device changes.

Streamlining, removing fluff, adding alt text
Source Link
DMGregory
  • 141k
  • 23
  • 258
  • 401

Tilting device about one axis in any orientation -using gyroscope help (Unity)sensor

Could someone please help me with a challenge I have? I am developing a Unity game where I need to tilt an iOS device to steer a ship as it flies in a straight line. The steering should be consistently accurate in any orientation, e.g. if the player holds the device directly in front of their face or if they are slouched over with the phone facing the ground etc. This is shown in the image below.

enter image description herePhone upright, rolling to the right / Phone flat, yawing to the right

A summary of my needs are:

  • Tilt the device to alter the on-screen ship's rotation (one axis only - in Unity this is the object's y-axis since it is a top-down 3D game). This is why I say "tilt" (think Temple Run), panning around in space to change all axes is not necessary and needs to be prevented.
  • I need to know how quickly the user is tilting their device to control the steering speed
  • I need to know the current tilt angle at any instance
  • I need to enforce a maximum tilt angle (e.g. tilting beyond +/- 45 degree has no further effect on the ship)
  • I need smoothness and no jerkiness

Can someone with knowledge please advise me how to achieve this with the gyroscope in Unity? I have been experimenting with my phone using the Unity Remote app and playing around with the Input.gyroInput.gyro and Input.accelerationInput.acceleration functions, but I cannot make sense of the angle data as the pitch and yaw of the device changes. As I say I need consistent behaviour. Some clear guidance would be appreciated tremendously!

I am really surprised by how few tutorials there are on this subject. I have done a lot of searching but there is very little advice online, which is strange since this seems like a very standard method of control.

Tilting device about one axis in any orientation - gyroscope help (Unity)

Could someone please help me with a challenge I have? I am developing a Unity game where I need to tilt an iOS device to steer a ship as it flies in a straight line. The steering should be consistently accurate in any orientation, e.g. if the player holds the device directly in front of their face or if they are slouched over with the phone facing the ground etc. This is shown in the image below.

enter image description here

A summary of my needs are:

  • Tilt the device to alter the on-screen ship's rotation (one axis only - in Unity this is the object's y-axis since it is a top-down 3D game). This is why I say "tilt" (think Temple Run), panning around in space to change all axes is not necessary and needs to be prevented.
  • I need to know how quickly the user is tilting their device to control the steering speed
  • I need to know the current tilt angle at any instance
  • I need to enforce a maximum tilt angle (e.g. tilting beyond +/- 45 degree has no further effect on the ship)
  • I need smoothness and no jerkiness

Can someone with knowledge please advise me how to achieve this with the gyroscope in Unity? I have been experimenting with my phone using the Unity Remote app and playing around with the Input.gyro and Input.acceleration functions, but I cannot make sense of the angle data as the pitch and yaw of the device changes. As I say I need consistent behaviour. Some clear guidance would be appreciated tremendously!

I am really surprised by how few tutorials there are on this subject. I have done a lot of searching but there is very little advice online, which is strange since this seems like a very standard method of control.

Tilting device about one axis in any orientation using gyroscope sensor

I am developing a Unity game where I need to tilt an iOS device to steer a ship as it flies in a straight line. The steering should be consistently accurate in any orientation, e.g. if the player holds the device directly in front of their face or if they are slouched over with the phone facing the ground etc. This is shown in the image below.

Phone upright, rolling to the right / Phone flat, yawing to the right

A summary of my needs are:

  • Tilt the device to alter the on-screen ship's rotation (one axis only - in Unity this is the object's y-axis since it is a top-down 3D game). This is why I say "tilt" (think Temple Run), panning around in space to change all axes is not necessary and needs to be prevented.
  • I need to know how quickly the user is tilting their device to control the steering speed
  • I need to know the current tilt angle at any instance
  • I need to enforce a maximum tilt angle (e.g. tilting beyond +/- 45 degree has no further effect on the ship)
  • I need smoothness and no jerkiness

Can someone with knowledge please advise me how to achieve this with the gyroscope in Unity? I have been experimenting with my phone using the Unity Remote app and playing around with the Input.gyro and Input.acceleration functions, but I cannot make sense of the angle data as the pitch and yaw of the device changes.

added 20 characters in body
Source Link
Cato
  • 103
  • 1
  • 9
Loading
Source Link
Cato
  • 103
  • 1
  • 9
Loading