In Unity, Swipe to rotate an object and when it reach 30° snap it to 90°

1.8k views Asked by At

The problem I wanted to solve :

  1. When I swipe the screen in the right direction, the cube starts to rotate on the Y axis,
  2. and when it reach 30°, the cube y rotation snaps smoothly to 90°. And by smoothly i mean a fast animation to 90° and not abrupt change to it. But this is a second issue, not the most important. enter image description here

The same for the left direction with negative values.

I tried and combined a lot of codes in vain, read about quaternion and eulers yet couldn't figure a proper solution. I hope you guys could help me with your knwoledge as am new to unity. Thank you very much.

1

There are 1 answers

0
Santi Paprika On

As stated by the user BIELIK in this thread, you can rotate an object via swipe using the following code:

#if UNITY_EDITOR
                float x = -Input.GetAxis("Mouse X");
#elif UNITY_ANDROID

                float x = -Input.touches[0].deltaPosition.x;
#endif
                transform.rotation *= Quaternion.AngleAxis(x * speedRotation, Vector3.up);

(of course, you need to attach the component where this belongs to the GameObject you want to rotate)

Note that the first if condition is used to ease testing on the Unity editor, so that you don't need to build the app into your device every time you want to test it (in case you are building for phones).

About the snapping feature, you could use some basic logic:

//call this function from your update method
//snappedAngle is the angle where snapping is fixed (in your drawing, would be 0)
//snapThresholdAngle is the angle you decide to apply the snapping once surpassed (in your case, 30)

CheckSwipeProgress(snappedAngle, snapThresholdAngle) {
    float currentAngle = transform.eulerAngles;
    if (currentAngle > snappedAngle + snapThresholdAngle) {
        snappedAngle = (snappedAngle > 265) ? snappedAngle = 0 : snappedAngle += 90;
    }
    //in this case we need to implicitly check the negative rotation for the snapped angle 0, since eulerAngles have range [0,360]
    else if (currentAngle < snappedAngle - snapThresholdAngle || ((snappedAngle == 0) && currentAngle < 360 - snapThresholdAngle && currentAngle > 270)) {
        snappedAngle = (snappedAngle < 5) ? snappedAngle = 270 : snappedAngle -= 90;
    }
    transform.eulerAngles.y = snappedAngle;
    //if you implement interpolation, it would substitute the line right above this one.
}

Notice that for the ternary conditions I try to find the singular cases (270 degrees, or 0 degrees), but I compare with a slightly lower/greater number. It is only to ensure numerical precision (avoiding ==), and it won't have any behavioral impact on your app, because snappedAngle can only be 0, 90, 180, and 270.

Notice as well that you can substitute rotation and eulerAngles with localRotation and localEulerAngles respectively, according to your needs.

Finally, about interpolation, there are plenty of threads that explain how to perform it. Check this one. The only thing to take into account is the singular cases because if you interpolate from 310 to 0 (e.g.), the movement will follow the opposite direction. You will need to interpolate between 310 and 360, and afterward assign the yaw value to 0.