I need to instantiate an object inside a donut instead of a circle

I need to instantiate an object inside a donut instead of a circle.

(donut or a custom game object)

public Transform prefab;
public int instances = 5000;
public float radius = 50f;

void Start()
{
    for (int i = 0; i < instances; i++)
    {
        Transform t = Instantiate(prefab);
        t.localPosition = Random.insideUnitCircle * radius;
        t.SetParent(transform);
    }
}

Thansks!

Just do a two step calculation. First you can use Random.insideUnitCircle.normalized to get a normalized direction vector. This just determines the direction. Now we just need to scale the length of that vector with appropriate values. Though if you want a uniform distribution we can not just use a radius that is within your desired range because you would get a higher density at the center as you can see here. The trick is the use the square root of the unit radius. So what we need to do is calculate the thicknees of the ring, map our “square rooted” radius onto this value and add the inner radius. This should give us a uniform distribution inside the ring.

// given:
float innerRadius = 35;
float outerRadius = 50;

// calculated
float ratio = innerRadius / outerRadius;
float radius = Mathf.Sqrt(Random.Range(ratio*ratio, 1f)) * outerRadius;
Vector3 point = Random.insideUnitCircle.normalized * radius ;

If the ring radius is rather large and the ring thickness relatively small the difference in distribution usually doesn’t matter much. In this case we could simply do:

Vector3 point = Random.insideUnitCircle.normalized * Random.Range(innerRadius, outerRadius);

Though as i mentioned you get a slightly higher density at the inner radius and the density gets lower as you go to the outer radius.

edit

I just realised that my initiali approach may not work properly. I’ve just changed the proper solution to get the right distribution.

Also note that using Random.insideUnitCircle.normalized to get a random normalized direction vector is just the quick and dirty solution. It does work fine, though we usually would simply calculate a random angle and use Sin and Cos to calculate a random vector:

float angle = Random.Range(0, 2f * Math.PI);
var dir = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));

Now we can use dir instead of Random.insideUnitCircle.normalized

You will need to calculate the spawn direction first then the actual distance from the center. See my implementation below:

 public Transform prefab;
 public int instances = 5000;
 
 public float radiusMin = 20f;
 public float radiusMax = 50f;
 void Start()
 {
    for (int i = 0; i < instances; i++)
    {
		var x = Random.Range(-1f, 1f);
		var y = Random.Range(-1f, 1f);
		var direction = new Vector3(x, 0f, y);
		var radius = Random.Range( radiusMin, radiusMax);
	 
        Transform t = Instantiate(prefab);		
		
        t.localPosition = direction * radius;
        t.SetParent(transform);
    }
 }