Hello to all!

The task is this:

There is a cube that we rotate along the 1st of 3 axes. The conditions of rotation are as follows: the axis along which we rotate the cube is considered free.

The angles on which the cube is turned should be a multiple of 90 degrees. But there is an exception, one face of the cube should be parallel to the player (or rather, the player's screen plane).

Now the problem: rotate the cube along the 1st of the three axes relative to the player:

myTransform - player rigidBody / rigidTransform - куб void FixedUpdate () { if (rigidBody){ Vector3 euler = rigidTransform.localEulerAngles;// rigidBody.rotation.eulerAngles;// rigidTransform.localRotation.eulerAngles;// Vector3 playerEulars = myTransform.eulerAngles;//rigidBody.rotation; Vector3 localAxis; Vector3 eulerAngleVelocity;// = localAxis * delta; if (axisIndex==0) { localAxis = rigidTransform.InverseTransformPoint (Vector3.up + rigidTransform.position); eulerAngleVelocity = localAxis * delta; euler.x = Mathf.Round (euler.x / 90f) * 90f; euler.z = Mathf.Round (euler.z / 90f) * 90f; Debug.Log ("OY"); } else { if (axisIndex==1) {// z axis localAxis = rigidTransform.InverseTransformPoint(myTransform.TransformPoint (Vector3.forward)+(rigidBody.position-myTransform.position)); eulerAngleVelocity = localAxis * delta; float displacement = euler.y - myTransform.eulerAngles.y; euler.y = playerEulars.y + Mathf.Round (displacement / 90f) * 90f; euler.x = Mathf.Round (euler.x / 90f) * 90f; Debug.Log ("OZ"); } else { if (axisIndex == 2) { localAxis = rigidTransform.InverseTransformPoint (myTransform.TransformPoint (Vector3.right) + (rigidBody.position - myTransform.position)); eulerAngleVelocity = localAxis * delta; float displacement = euler.y - myTransform.eulerAngles.y; euler.y = playerEulars.y + Mathf.Round (displacement / 90f) * 90f; euler.z = Mathf.Round (euler.z / 90f) * 90f; Debug.Log ("OX"); } else { eulerAngleVelocity = Vector3.zero; } } } rigidBody.rotation = Quaternion.Lerp (rigidBody.rotation, Quaternion.Euler(euler), 5f*Time.fixedDeltaTime); if (isLocalPlayer) { Quaternion deltaRotation = Quaternion.Euler(eulerAngleVelocity * 5000f * Time.fixedDeltaTime); rigidBody.rotation *= deltaRotation; } } } 

1) The cube is constantly turned to one of the faces to the player 2) Rotates along one of the axes 3) Attempts to return to a multiple of 90 degrees along the other axes along which it is not rotated.

The problem is, the cube sometimes starts to juggle if you try to rotate it because rotations in the euler lead to this (he is incorrectly trying to return the angle) ... Do you understand what is happening? Advise how to fix it)

    2 answers 2

    Get rid of the rotation through the corners of Euler. If you want everything to work without errors, you need to do everything through Quaternion . Here is a good explanation of what it is . When you need to rotate an object at a given angle do Quaternion using the method

    Quaternion q = Quaternion.AngleAxis(float angle, Vector3 axis);

    Now take the current rotation transform.rotation and multiply it by the resulting q . As a result, your object will add your specified rotation to the existing rotation.

    Even in your code it is embarrassing that you are trying to rotate rigidbody , if your cube is not kinematic, this can also affect, because your changes in the position of the object will contradict the work of physics.

    • Thanks for the answer. I figured out what quaternions are. Not so long ago, I realized that between Euler angles and quaternions it is not worth building mappings (before that, I had been stubbornly thinking that these sets could somehow be mapped into each other so that it looked adequate). "Even in your code it is embarrassing that you are trying to rotate rigidbody" - but I did not understand it. Why? - Alerr
    • Now I'm trying to make the cube turn to the nearest angle of a multiple of 90 degrees. Well, as I try, I read a book on quaternions, on gamedev.ru they give advice, but so far all is in vain - Alerr
    • If you have a rigidbody the Is Kinematic feature then animating through rotation transform.rotation is quite normal, but when you try an object that is processed in Unity physics (without such a tick) to move to the desired position in this way, then you actually get a teleport and the physics engine starts slowly go crazy. In this case, it is assumed that you rotate and move objects by force. In your case, you can make an object on kinematics and then everything will be fine - KingPeas

    If you want to rotate the cube relative to some object, you do not need to write any code at all. It is enough to place the cube in the hierarchy as a subgroup of the "player".

    And then via Quaternion.AngleAxis (float angle, Vector3 axis); set multiples of 90 degrees.