- Home /
Instantiate prefabs in a circle or elipsoid
Hey again!
I have a query. I'd like to instantiate objects in a for loop, but have them placed so they appear to be in a circle or ellipsoid, preferably ellipsoid.
I know it has something to do with maths, kind of wishing I didn't drop out, but it should be easy for someone to solve!
I am using the code snippet bellow to give an idea
for (i = 0; i < max; i++)
{
var newbead : GameObject = Instantiate (beadPrefab, Vector3(X , Y, 32 ), Quaternion.identity);}
So, what formulae would be used to calculate the values X and Y ?
If anything needs clearing up, please reply!
~ Nathan
Answer by duck · Sep 28, 2010 at 10:47 AM
Here you go. The comments explain most of it, although you may want to read up on radians. (They are just another way of measuring angles, as opposed to degrees).
I've also renamed a few vars for clarity.
var numPoints = 20; var centrePos = Vector3(0,0,32);
for (var pointNum = 0; pointNum < numPoints; pointNum++) {
// "i" now represents the progress around the circle from 0-1
// we multiply by 1.0 to ensure we get a fraction as a result.
var i = (pointNum * 1.0) / numPoints;
// get the angle for this step (in radians, not degrees)
var angle = i * Mathf.PI * 2;
// the X & Y position for this angle are calculated using Sin & Cos
var x = Mathf.Sin(angle) * radiusX;
var y = Mathf.Cos(angle) * radiusY;
var pos = Vector3(x, y, 0) + centrePos;
// no need to assign the instance to a variable unless you're using it afterwards:
Instantiate (beadPrefab, pos, Quaternion.identity);
}
this example works with global X and Y directions. But my orientation is different. i want to use X and Z directions, how can i fix that? Changing Sin or Cos?
@itscoolbro - the radius is the distance of the prefab from the center. You would set it with variables at the top to whatever you want the radius to be. If you had an ellipse, you may have var radiusX = 4 and var radiusY = 2. If you want a circle, then you would have only var radius = 3 and plug it in both places since it would be the same distance on all sides.
Answer by Jesse Anders · Sep 26, 2010 at 02:52 PM
Since you mentioned a circle, I'm going to assume you meant 'ellipse' rather than 'ellipsoid'.
Given a center point (Cx, Cy), an angle theta, and two radii, radiusX and radiusY, you can compute a point on the ellipse as follows:
x = Cx + cos(theta) * radiusX;
y = Cy + sin(theta) * radiusY;
To generate evenly distributed points on an ellipse, iterate over the range [0, 2pi) using a fixed step corresponding to how many points you want (e.g. if you want 20 points, the step will be 2pi/20).
This will create the points in the XY plane. If you need them to be in another cardinal plane or to be arbitrarily oriented, you can apply an appropriate transform to the points after they're generated. (In this case you can skip Cx and Cy and just incorporate the translation into the transform itself.)
Is it possible to add this into the code above, or as another example?
Here's a version of the script in C#. It also allows for users to decide whether the shape is specifically a circle or an ellipsoid or place it "on the horizontal axis."
public int numPoints = 20; //number of points on radius to place prefabs
public Vector3 centerPos = new Vector3(0,0,32); //center of circle/elipsoid
public GameObject pointPrefab; //generic prefab to place on each point
public float radiusX,radiusY; //radii for each x,y axes, respectively
public bool isCircular = false; //is the drawn shape a complete circle?
public bool vertical = true; //is the drawb shape on the xy-plane?
Vector3 pointPos; //position to place each prefab along the given circle/eliptoid
//*is set during each iteration of the loop
// Use this for initialization
void Start () {
for(int i = 0; i<numPoints;i++){
//multiply 'i' by '1.0f' to ensure the result is a fraction
float pointNum = (i*1.0f)/numPoints;
//angle along the unit circle for placing points
float angle = pointNum*$$anonymous$$athf.PI*2;
float x = $$anonymous$$athf.Sin (angle)*radiusX;
float y = $$anonymous$$athf.Cos (angle)*radiusY;
//position for the point prefab
if(vertical)
pointPos = new Vector3(x, y)+centerPos;
else if (!vertical){
pointPos = new Vector3(x, 0, y)+centerPos;
}
//place the prefab at given position
Instantiate (pointPrefab, pointPos, Quaternion.identity);
}
//keeps radius on both axes the same if circular
if(isCircular){
radiusY = radiusX;
}
}
Your answer
Follow this Question
Related Questions
Please help with some Vector math! :-) 1 Answer
Grid-based building system not working 1 Answer
How to use this code for instantiate? 0 Answers
Checking if object intersects? 1 Answer
Quaternion values at instantiation. 1 Answer