- Home /
The question is answered, right answer was accepted
Spawn Object Outside of Radius
Hey Guys,
I was wondering how would I spawn an enemy object outside of a player objects radius?
For example, I have enemy ship objects that spawn at random positions onto the play field. What I would like to do, is create a radius (let's say of 5) around the player so when a ship spawns, it doesn't spawn on top or next to the player. This also gives a chance for the player to react to an enemy spawn.
I'm not sure how I would go about this, so I don't have code for it. At the moment this is the code for my spawner:
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while (true) {
for (int i = 0; i < hazrdCount; i++)
{
GameObject hazard = hazards[Random.Range (0, hazards.Length)] ;
Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, Random.Range(-spawnValues.z, spawnValues.z));
Quaternion spawnRotation = Quaternion.identity;
Instantiate(hazard, spawnPosition, spawnRotation);
yield return new WaitForSeconds(spawnWait);
}
yield return new WaitForSeconds(waveWait);
}
}
Right now the enemy objects don't spawn outside of the world, which is good. But I would like to make sure no matter where the player object is on the map, enemy objects won't spawn relative to the player object of a given radius.
Thanks, Mark.D
Answer by jim3878 · May 27, 2018 at 02:49 PM
This will make sure enemy ship will spawn at a distance between 5.0 to 20.0.
float minDistance = 5.0;
float maxDistance = 20.0;
float distance = Random.Range( minDistance, maxDistance );
float angle = Random.Range( -Mathf.PI, Mathf.PI );
Vector3 spawnPosition = playerTransform.position ;
spawnPosition += new Vector3( Mathf.Cos( angle ), 0, Mathf.Sin( angle ) ) * distance;
spawnPosition.x = Mathf.Clamp( spawnPosition.x, -spawnValues.x, spawnValues.x );
spawnPosition.y = spawnValues.y ;
spawnPosition.z = Mathf.Clamp( spawnPosition.z, -spawnValues.z, spawnValues.z );
Hi Jim,
I believe I have this some what working now, I can get the enemies to spawn in a random location from $$anonymous$$Distance * maxDistance, but this doesn't seem to make it relative to the player position. It is only relative to centre position. Am I missing something?
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while (true) {
for (int i = 0; i < hazrdCount; i++)
{
float $$anonymous$$Distance = 30f;
float maxDistance = 35.0f;
float distance = Random.Range($$anonymous$$Distance, maxDistance);
float angle = Random.Range(-$$anonymous$$athf.PI, $$anonymous$$athf.PI);
GameObject hazard = hazards[Random.Range(0, hazards.Length)];
Vector3 spawnPosition = hazard.transform.position;
spawnPosition += new Vector3($$anonymous$$athf.Cos(angle), 0, $$anonymous$$athf.Sin(angle)) * distance;
spawnPosition.x = $$anonymous$$athf.Clamp(spawnPosition.x, -spawnValues.x, spawnValues.x);
spawnPosition.y = spawnValues.y;
spawnPosition.z = $$anonymous$$athf.Clamp(spawnPosition.z, -spawnValues.z, spawnValues.z);
Quaternion spawnRotation = Quaternion.identity;
Instantiate(hazard, spawnPosition, spawnRotation);
yield return new WaitForSeconds(spawnWait);
}
yield return new WaitForSeconds(waveWait);
if (gameOver)
{
restartText.text = "Press 'R' for Restart";
restart = true;
break;
}
}
}
Vector3 spawnPosition = player.transform.position;
or if you have the main camera attached to the player then you could do this:
Vector3 spawnPosition=Camera.main.transform.position
Hmmm I tried that, but it doesn't seem to work. I added a DrawOnGizmos() to the spawn position that way I can see the spawn radius and it seems to just go in random locations all the time... I'll create a snippet of what it's doing so you can see :) Thanks for your wonderful help :)
This has several issues. First of all the point you pick on the disk is not uniformly distributed. You get a higher density at the inner circle. Also your clamping increases the density in the corners of your clamping region.
A common way to fix the center concentration is to take the square root of the radius. However this only works for picking a point inside a complete circle. We could adjust the formula to get a uniform distribution at least inside the annulus. Though the clamping would still cause a higher density towards the corners.
If the spawning area can be a circle in the first place it would be possible to get a uniform distribution inside a ring / annulus. If the spawning area should be a rectangle then @tormentoarmagedoom's answer is the only one that guarantees a uniform distribution.
Answer by tormentoarmagedoom · May 27, 2018 at 01:56 PM
Good day.
As you randomize the spawn point, you can just check the distance from the spawnpoint to the player, and if is too close, recalculate the spawnpoint, like this:
GameObject hazard = hazards[Random.Range (0, hazards.Length)] ;
Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, Random.Range(-spawnValues.z, spawnValues.z));
while (Vector3.distance(spawnPosition, player.transform.position) < 50)
{
spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, Random.Range(-spawnValues.z, spawnValues.z));
}
Quaternion spawnRotation = Quaternion.identity;
Instantiate(hazard, spawnPosition, spawnRotation);
Now, it will be doing the While sentence remaking the spawnpoint position until the distance is more than 50.
Be aware to check the while condition before play the game in Editor, because if while never become false, it willstay isidie the while "forever" and Unity will stay blocked, you you will need to Ctl+Alt+Sup to stop Unity ... so save the project every time until you are sure the while works perfect.
Bye! :D
$$anonymous$$gest a solution that may take an unknown duration to calculate, and worse yet, that can crash the built game or the editor is not very smart.
Upvoted since it actually provides a uniform distribution. Yes, it's not an optimal solution and with the wrong setting could lead to an infinite loop. However it is actually the only solution to pick a uniformly distributed random point inside a rectangle and exclude a spherical region in the center. If the ratio between the spawnValues and the inner radius is getting small (or even below 1f) the performance would drastically drop (or even hang your application).
Answer by Unified2000 · May 27, 2018 at 02:30 PM
This will return a random position that's 20 to 50 meters away:
Vector3 pos=new Vector3(Random.value-0.5f,0,Random.value-0.5f).normalized*Random.Range(20,50);
But this does not control if is inside the world map...
This work but has a non-uniform distribution. The density on the inner circle is higher than on the outer circle.