Repository: FlaxEngine/FlaxEngine
File: Source/Engine/Utilities/Extensions.cs (C#)

Code before:
        /// <param name="random">An instance of <see cref="Random"/>.</param>
        /// <returns>A random <see cref="Vector3"/>.</returns>
        public static Vector3 NextVector3(this Random random)
        {
            Vector3 output;

            do
            {
                // Create random float with a mean of 0 and deviation of ±1
                output.X = NextFloat(random) * 2.0f - 1.0f;
                output.Y = NextFloat(random) * 2.0f - 1.0f;
                output.Z = NextFloat(random) * 2.0f - 1.0f;

            } while (output.LengthSquared > 1 || output.LengthSquared < 1e-6f);

            output *= (1.0f / (float)Math.Sqrt(output.LengthSquared));

            return output;
        }

        /// <summary>
        /// Generates a uniformly distributed random unit length vector point on a unit sphere in 2D.
        /// </summary>
        /// <param name="random">An instance of <see cref="Random"/>.</param>
        /// <returns>A random <see cref="Vector2"/>.</returns>
        public static Vector2 NextVector2(this Random random)
        {
            Vector2 output;

            do
            {
                output.X = NextFloat(random) * 2.0f - 1.0f;
                output.Y = NextFloat(random) * 2.0f - 1.0f;

            } while (output.LengthSquared > 1 || output.LengthSquared < 1e-6f);

            output *= (1.0f / (float)Math.Sqrt(output.LengthSquared));

            return output;
        }

        /// <summary>
        /// Generates a random <see cref="Color"/>.
        /// </summary>
        /// <param name="random">An instance of <see cref="Random"/>.</param>
        /// <param name="trueRandom">Should the color be generated from a single random Hue value or separate values for each channel.</param>
        /// <param name="randomAlpha">Randomize the alpha value.</param>
        /// <returns>A nice random <see cref="Color"/>.</returns>
        public static Color NextColor(this Random random, bool trueRandom, bool randomAlpha)
        {
            float alpha = randomAlpha ? NextFloat(random) : 1f;

Review comment (performance):
I decided to benchmark this guy and its performance is on par with the trigonometry based variant (`PointInACircle`). However, since the trig based variant gives more consistent results, I suppose it might be preferable?

So, my recommendation would be to replace the code of this method with the code from `PointInACircle` and then remove `PointInACircle`.

It might also be worthwhile to look into the trig based approach for the NextVector3 method

Benchmarking code
```cs
class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<Benchmark>();
    }
}

public struct Vector2
{
    public float X;
    public float Y;
}

public class Benchmark
{
    private readonly Random _random = new Random();
    public Benchmark()
    {
    }

    [Benchmark]
    public Vector2 RejectionBased() => NextVector2();

    [Benchmark]
    public Vector2 TrigBased() => NextVector2Other();


    public Vector2 NextVector2()
    {
        Vector2 output;
        float lengthSquared;
        do
        {
            output.X = (float)_random.NextDouble() * 2.0f - 1.0f;
            output.Y = (float)_random.NextDouble() * 2.0f - 1.0f;

            lengthSquared = output.X * output.X + output.Y * output.Y;
        } while (lengthSquared > 1 || lengthSquared < 1e-6f);

        float inverseSquare = (1.0f / (float)Math.Sqrt(lengthSquared));

        output.X *= inverseSquare;
        output.Y *= inverseSquare;

        return output;
    }

    public Vector2 NextVector2Other()
    {
        float radius = (float)_random.NextDouble() * 2.0f * MathF.PI;

        return new Vector2()
        {
            X = (float)Math.Cos(radius),
            Y = (float)Math.Sin(radius)
        };
    }
}
```

Code after:
        /// <summary>
        /// Generates a random <see cref="Vector2"/> point in a circle of a given radius.
        /// </summary>
        /// <param name="random">An instance of <see cref="Random"/>.</param>
        /// <param name="radius">Radius of circle. Default 1.0f./>.</param>
        /// <returns>A random <see cref="Vector2"/>.</returns>
        public static Vector2 NextUnitVector2(this Random random, float radius = 1.0f)
        {
            var randomRadius = (float)random.NextDouble() * radius;

            return new Vector2
            {
                X = (float)Math.Cos(random.NextDouble()) * randomRadius,
                Y = (float)Math.Sin(random.NextDouble()) * randomRadius,
            };
        }

        /// <summary>
        /// Generates a uniformly distributed random unit length vector point on a unit sphere.
        /// </summary>
        /// <param name="random">An instance of <see cref="Random"/>.</param>
        /// <returns>A random <see cref="Vector3"/>.</returns>
        public static Vector3 NextUnitVector3(this Random random)
        {
            Vector3 output;
            float l;

            do
            {
                // Create random float with a mean of 0 and deviation of ±1
                output.X = NextFloat(random) * 2.0f - 1.0f;
                output.Y = NextFloat(random) * 2.0f - 1.0f;
                output.Z = NextFloat(random) * 2.0f - 1.0f;

                l = output.LengthSquared;

            } while (l > 1 || l < Mathf.Epsilon);

            output.Normalize();

            return output;
        }

        /// <summary>
        /// Gets a random <see cref="Vector2"/> with components in a given range.
        /// </summary>
        /// <param name="random">An instance of <see cref="Random"/>.</param>
        /// <param name="min">The minimum value.</param>
        /// <param name="max">The maximum value.</param>
        /// <returns>A random <see cref="Vector2"/>.</returns>
        public static Vector2 NextVector2(this Random random, float min = 0.0f, float max = 1.0f)