- Home /
Randomly placing an object outside of a box but within a certain range
Hey guys, I've started learning Unity over the past month or so and am current working on an Asteroids game. I'm currently able to spawn different size asteroids with random rotation and velocity (that are bounded within a range). However, one thing I am struggling with is to get the asteroid to spawn in a random place, OFF camera, and move into camera.
I currently have a ScreenWrap script that will automatically wrap objects to the opposite side of the stage upon exiting one side. For example, if you fly your ship off the left side of the stage you will reappear coming from the right edge of the stage.
What I'm trying to do now, is spawn the asteroids off screen, apply the velocity, and then activate the ScreenWrap script upon entering the stage.
Here is what I have so far to place the asteroids (in my asteroids script):
function SetRandomPositions () {
// Start the asteroid in a random place inside the camera
// Get the edge positions of the camera
var limitMin:Vector3 = Camera.main.ScreenToWorldPoint(Vector3(0, 0, Camera.main.transform.position.y));
var limitMax:Vector3 = Camera.main.ScreenToWorldPoint(Vector3(Screen.width, Screen.height, Camera.main.transform.position.y));
// Place the asteroid on the stage in a random place
transform.position.x = Random.Range(limitMin.x, limitMax.x);
transform.position.z = Random.Range(limitMin.z, limitMax.z);
}
This script currently just places them on the screen in a random place. However, I need to place them OUTSIDE the stage when spawning. This way an asteroid doesn't spawn on top of the player, as well as, not looking like it just appears out of nowhere.
There is a variable inside of the ScreenWrap script that has the object's offset. This variable allows the object to move off the screen just enough so you don't see it "jump" to the other side. Using this variable, I started to write an "outer spawn box", but I can't figure out how to constrain the asteroid to be inside the "spawn box" but outside the "stage box".
var outerSpawnMin:Vector3 = Vector3(limitMin.x + (asteroidSizeOffset * 2), limitMin.z + (asteroidSizeOffset * 2));
var outerSpawnMax:Vector3 = Vector3(limitMax.x + (asteroidSizeOffset * 2), limitMax.z + (asteroidSizeOffset * 2));
Here is a link to play the current build to get an idea, and attached is an image that best describes what I'm trying to do. Any help would be greatly appreciated!
$$anonymous$$gestions below will all work. Sometimes when I'm dealing with this issue, I just call Random.Range() until I have something something that works. For example, for X and Y:
do {x = Random.Range($$anonymous$$Scene, maxScene } while (x >= $$anonymous$$Stage && x
Answer by Squabbler · Jan 21, 2013 at 06:50 PM
EDITED: This is what I went with.
// top/bottom (true) or left/right (false)
if (Random.Range(0, 2)) {
// set x position randomly
transform.position.x = Random.Range(outerSpawnMin.x, outerSpawnMax.x);
// spawn on top (true) or bottom (false)
if (Random.Range(0, 2)) {
// set the z position to top
transform.position.z = outerSpawnMax.y;
} else {
// set the z position to bottom
transform.position.z = outerSpawnMin.y;
}
} else {
// set z position randomly
transform.position.z = Random.Range(outerSpawnMin.y, outerSpawnMax.y);
// spawn on left (true) or right (false)
if (Random.Range(0, 2)) {
// set the x position to left
transform.position.x = outerSpawnMin.x;
} else {
// set the x position to right
transform.position.x = outerSpawnMax.x;
}
}
Answer by cdrandin · Jan 21, 2013 at 06:40 AM
if you know your camera area, all you need to do is add onto the sides. so, if you camera view is 800x600. So.. (0,0) top left (800,600) bottom right. TO get the outsides, just increase it by lets say 100 units, both directions. Expanded screen: (-100,-100) top left, (900,700). so you know to spawn the asteroids between (-100,0),(0,-100),(900,600),(800,700) then take the difference in the points of your screen. Which will eventually give you coordinates in the red boundaries corresponding with the picture above.
I think this is right, unless I messed up in the math some where.
If this isn't making an sense, you could just have box colliders outside the camera view and spawn within the area of the colliders, which Unity also has a function for spawning randomly within a box area.
Answer by Owen-Reynolds · Jan 21, 2013 at 05:06 PM
Since you only have 4 areas (top, bottom, left, right,) roll 1-4 for which area, then spawn within that box (I think this is the last Para from cdranin.)
That will give a small extra chance to spawn in the corners (since the each corner is in 2 boxes.) If it's even noticeable, could shrink the boxes a bit.
The other way, which works for any sort of oddly shaped area, is "roll until I'm happy":
roll random position in giant red+blue box
while ( inside blue box )
reroll random position in giant red+blue box
Save all before testing it, since if you mess up the coords, if can loop forever and force you to abort Unity.
This is basically the idea I had. It's very similar to yours, but randomly selecting each side individually ins$$anonymous$$d of 1-4. if(1/0) to select vertical/horizontal, followed by get random position on that axis, then if(1/0) to select which side and max/$$anonymous$$ of that axis. This will basically put the asteroid randomly on the top/right/bottom/left edge at a random position on that axis.
Answer by nathanthesnooper · Oct 14, 2016 at 04:14 AM
Using Owen's method, I made this code. The length is mostly preventing the corners from getting too many spawns.
int area = Random.Range (0, 4);
Vector3 pos = GameObject.Find("Player").transform.position;
if (area == 0) {
pos.x += Random.Range (-Range, Range + 1 - (Range - InnerRange));
pos.z += Random.Range (InnerRange, Range + 1);
}
if (area == 1) {
pos.x += Random.Range (InnerRange, Range + 1);
pos.z += Random.Range (-Range + (Range - InnerRange), Range + 1);
}
if (area == 2) {
pos.x += Random.Range (-Range + (Range - InnerRange), Range + 1);
pos.z -= Random.Range (InnerRange, Range + 1);
}
if (area == 3) {
pos.x -= Random.Range (InnerRange, Range + 1);
pos.z += Random.Range (-Range, Range + 1 - (Range - InnerRange));
}
Your answer
Follow this Question
Related Questions
When spawning to a grid, how to only spawn one object next to another? 1 Answer
collider2D.bounds.Contains not working properly 3 Answers
Instantiate random object from Array 2 Answers
random spawning of platforms. Overlapping and 2x2 spawning issue. 1 Answer
Multiple spawn location with random game object in random time spawn c# 1 Answer