There are a few methods for doing this. I'll provide two. The first is a one-liner that uses Quaternions to generate a random vector and then rotate it into place:
Vector3 RandomTangent(Vector3 vector) {
return Quaternion.FromToRotation(Vector3.forward, vector) * (Quaternion.AngleAxis(Random.Range(0f, 360f), Vector3.forward) * Vector3.right);
}
The second is longer, more mathematically rigorous, and less platform dependent:
Vector3 RandomTangent(Vector3 vector) {
var normal = vector.normalized;
var tangent = Vector3.Cross(normal, new Vector3(-normal.z, normal.x, normal.y));
var bitangent = Vector3.Cross(normal, tangent);
var angle = Random.Range(-Mathf.PI, Mathf.PI);
return tangent * Mathf.Sin(angle) + bitangent * Mathf.Cos(angle);
}
Here are some notes on their differences:
- Both of these functions generate a random perpendicular vector (or "tangent") with a uniform distribution.
- You can measure the accuracy of these functions by getting the angle between the input and the output. While most of the time it will be exactly 90, there will sometimes be very minor deviations, owing mainly to floating point rounding errors.
- While neither of these functions generate large errors, the second function generates them far less frequently.
- Initial experimentation suggests the performance of these functions is close enough that the faster function may vary depending on platform. The first one was actually faster on my machine for standard Windows builds, which caught me off guard.
- If you're prepared to assume that the input to the second function is a normalized vector, you can remove the explicit normalization of the input and get a performance increase. If you do this and then pass it a non-normalized vector, you'll still get a perpendicular vector as a result, but its length and distribution will no longer be reliably uniform.
- In the degenerate case of passing a zero vector, the first function will generate random vectors on the XY plane, while the second function will propagate the error and return a zero vector itself.