- Home /
random.onUnitCircle ?
there's random onUnitSphere, but it doesn't work as random.onUnitCircle if it's being reduced from Vector3 to Vector2.
what are there other ways of choosing a random point on a circle.(not inside it, not outside, just on the very edge)
Answer by Jumbo the Great · Jan 09, 2013 at 06:09 AM
THE EASIEST WAY IS THIS:
Random.insideUnitCircle.normalized;
Just random inside unit circle first, and then normalized it. This will convert the vector to be 1 in magnitude, which is the same as random on unit circle. Hope this helps!
This seems like a nice, concise solution. However, I think there is a very rare edge-case that this would fail under, which is if Random.insideUnitCircle returns (0, 0). In that case, according to this documentation, you would get a zero vector back after normalizing. If the code using this depends on getting a normalized vector, this might not be the best solution.
Yes, this case would be extremely rare, but that also makes for a bug that more than likely will never, ever be fixed. In addition, if this operation was performed many times (in a loop, or whatnot), the frequency of occurrences would go up. Given this (very rare) failure case, wrapping one of the less elegant solutions in a method might be better.
Then why not just...
IEnumerator TestNullVector()
{
var randomPointOnCircle = Random.insideUnitCircle.normalized;
// Handle edge case of getting a 0f, 0f vector.
var nullVector = false;
if(randomPointOnCircle == new Vector2(0f, 0f)) { nullVector = true; }
while(nullVector)
{
randomPointOnCircle = Random.insideUnitCircle.normalized;
if(randomPointOnCircle != new Vector2(0f, 0f)) { nullVector = false; }
}
StartCoroutine(TestNullVector());
yield return null;
}
Answer by zannghast · Nov 08, 2010 at 01:45 AM
Similar to Peter's answer, you could get a random angle and pass that to a custom function that accepts an angle and radius.
It would be akin to something like:
Vector2 GetUnitOnCircle(float angleDegrees, float radius) {
// initialize calculation variables
float _x = 0;
float _y = 0;
float angleRadians = 0;
Vector2 _returnVector;
// convert degrees to radians
angleRadians = angleDegrees * Mathf.PI / 180.0f;
// get the 2D dimensional coordinates
_x = radius * Mathf.Cos(angleRadians);
_y = radius * Mathf.Sin(angleRadians);
// derive the 2D vector
_returnVector = new Vector2(_x, _y);
// return the vector info
return _returnVector;
}
sorry to bring back an old tread. Just happened to see it and I noticed that degrees to radians should be $$anonymous$$athf.PI / 180.0 since there are 2pi in a circle.
Answer by Peter G · Nov 08, 2010 at 12:36 AM
You could get a random value between 0
and 2pi
radians then find the sin and cos of that and make them your values in a Vector2
.
Here's the helper function I created based on your comment. It works great!
public static Vector2 RandomPointOnUnitCircle(float radius)
{
float angle = Random.Range (0f, $$anonymous$$athf.PI * 2);
float x = $$anonymous$$athf.Sin (angle) * radius;
float y = $$anonymous$$athf.Cos (angle) * radius;
return new Vector2 (x, y);
}
Answer by avatara359 · Dec 14, 2012 at 09:20 PM
Another way: 1. Use Unity methods to get a random point. 2. Normalize the vector to be one unit long. 3. Multiply by radius to get desired length.
public static Vector2 RandomOnUnitCircle2( float radius)
{
Vector2 randomPointOnCircle = Random.insideUnitCircle;
randomPointOnCircle.Normalize();
randomPointOnCircle *= radius;
return randomPointOnCircle;
}
public static Vector3 RandomOnUnitSphere( float radius)
{
Vector3 randomPointOnCircle = Random.insideUnitSphere;
randomPointOnCircle.Normalize();
randomPointOnCircle *= radius;
return randomPointOnCircle;
}
Answer by GingerLoaf · Dec 30, 2014 at 02:23 AM
I was surprised to see so much resistance to trig here. As game programmers, we should either strive to make our code optimal (not use a bunch of high-level calls that bring in extra overhead) as well as improve what we know as far as not just programming, but mathematics. Peter G deserves the answer to this thread, as he provided the answer. I can't say whether or not it is the absolute best option, but it is most certainly hard to think of something that can compete. Using Peter G's suggestion, I was able to produce this:
float randomAngle = Random.Range(0f, Mathf.PI * 2f);
Vector2 randomPointAround2DCircumference = new Vector2(Mathf.Sin(randomAngle), Mathf.Cos(randomAngle)).normalized;
Wrapping this in a function should now be fairly easy:
public Vector2 GetPointOnUnitCircleCircumference()
{
float randomAngle = Random.Range(0f, Mathf.PI * 2f);
return new Vector2(Mathf.Sin(randomAngle), Mathf.Cos(randomAngle)).normalized;
}
I have tested this in Unity and I am seeing the intended results. Enjoy!
Of course you don't need to normalize that. It's already normalized ;)