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?
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;
}