I’m trying to instantiate some asteroid prefabs inside a torus shape (surrounding the planet) that is in the scene. When the player enters the shapes collider it changes the name of the map to the current area (asteroid field). Now, how would I instantiate the asteroid prefabs only inside the shape, and give a min and max distance they can be instantiated from each other?
if it has a mesh, use its mesh.bounds, using prefabs, position + scale, take that as a cubic object, then use a random to get the vector3 position withing the position and scale, and if that position is inside mesh.bounds, then accept it, if its not keep executing that random(means it should be in a while loop), good luck and happy coding
In the case of a torus, you can handle it mathematically. You can define two radii…the radius between the center of the torus and the mid-line of the tube that forms the torus, and the radius of the tube. First find a random point on the mid-line, then using a tangent to the mid-line as an axis, swing a second vector around randomly. You will get a point inside the torus. The distribution will not be even, but in playing, it was hard to tell.
Attach the following script to a game object. The position and rotation of game object will be the position and rotation of the torus. Drag and drop a prefab onto the ‘prefab’ variable. I used a sphere (0.1, 0.1, 0.1) in size:
using UnityEngine;
using System.Collections;
public class Torus : MonoBehaviour {
public float ringMidlineRadius = 4.0f;
public float tubeRadius = 0.75f;
public GameObject prefab;
void Start () {
for (int i = 0; i < 5000; i++) {
Instantiate(prefab, RandInTorus(), Quaternion.identity);
}
}
Vector3 RandInTorus() {
Vector3 dir = Vector3.up * ringMidlineRadius;
dir = Quaternion.AngleAxis (Random.Range (0.0f, 360.0f), Vector3.forward) * dir;
Vector3 axis = Vector3.Cross (dir, Vector3.forward);
Vector3 dir2 = dir.normalized * Random.Range (0.0f, tubeRadius);
dir2 = Quaternion.AngleAxis (Random.Range (0.0f, 360.0f), axis) * dir2;
return transform.TransformPoint (dir + dir2);
}
}
Well basically use the equation of the shape to work out the positions, in the case of a torus or doughnut you can use:
- The circle which forms the centre of the torus.
So I guess that’s something like:
var up = Vector3.up; //Or whatever the "up" of the orientation of the torus is
var pos = Quaternion.AngleAxis(Random.value * 360, up) * Vector3.forward * radius;
- An offset from the circle based on the radius of the torus cross-section
Perhaps:
pos += up * (Random.value - 0.5f) * crossSectionRadius * 2;
Then to ensure that you have no collisions you could start by allocating the enemies around the circle rather than just using * 360 in the first part - or you could test whether there’s anything in the way using Physics.OverlapSphere or something.