Search code examples
unity-game-engine3drotation

Changing direction in 3D


I am working on a 3D project, in Unity.

I have an object moving in a confined space. The object have a fixed velocity, and it bounces back once they reach the space limit.

I want it to change direction once every n seconds.

The problem I am facing is: How to rotate a 3D vector by a given angle.

In 2D is pretty easy, while in 3D I am not sure how to handle it.

Can someone help me with that?


Solution

  • I managed to do the thing I wanted. Firstly, I computed a Vector3 that was orthogonal to the current transform.forward; then I rotate that angle around itself of a random angle between 0 and 360 degrees, and finally I used that generated vector as axis for the rotation to apply to the velocity of my object.

    Here is the code:

    public static void ChangeObjectDirection(Rigidbody rb, int angle, float velocity)
            {
                // get the transform of rb
                var t = rb.gameObject.transform;
    
                // get the current velocity direction
                var direction = t.forward;
                // generate a normalized orthogonal vector wrt the current velocity direction
                var orth = OrthogonalVector(direction);
    
                // rotate the orthogonal vector around himself of a random angle between 0 and 360
                orth = Quaternion.AngleAxis(Random.Range(0, 360), direction) * orth;
    
                // generate random rotational angle in degrees
                var randomAngle = Random.Range(-angle, angle);
    
                // rotate the current velocity direction of randomAngle around the orth vector
                direction = Quaternion.AngleAxis(randomAngle, orth) * direction;
    
                // update the velocity direction
                t.forward = direction;
                rb.velocity = direction * velocity;
            }
    
    private static Vector3 OrthogonalVector(Vector3 u)
            {
                var a = u.x;
                var b = u.y;
                var c = u.z;
    
                Vector3 v;
    
                if (b == 0 && c == 0)
                {
                    v = new Vector3(0f, 1f, 1f);
                } 
                else if (a == 0 && c == 0)
                {
                    v = new Vector3(1f, 0f, 1f);
                } 
                else if (a == 0 && b == 0)
                {
                    v = new Vector3(1f, 1f, 0f);
                }
                else
                {
                    if (c != 0)
                    {
                        // ax + bx + cz == 0 with x == 1 and y == 1 => z = (-a - b) / c
                        v = new Vector3(1f, 1f, (-a - b) / c);
                    }
                    else
                    {
                        // ax + bx + cz == 0 with y == 1 and z == 1 => c = (-b - c) / a
                        v = new Vector3((-b - c) / a, 1f, 1f);
                    }
                }
    
                v = v.normalized;
                return v;
            }