- Home /
How can i keep the spawned objects to be inside a given area ?
In the script i spawn cubes randomly inside the walls area. The walls area can be 5x5 or 100x500 or 23x76 The problem is when a cube is spawned too close to one of the walls part of the cube is inside the area and part of it is outside the walls area.
I'm trying to use padding and Math.Clamp inside the GenerateRandomPositions method but it's not working.
The idea i think is that if for example the walls area is position at for example top left corner 32,40 and the bottom right corner is 120,130 then using padding and math.calmp to narrow the area to position randomly the cubes at 30,38 and 110,120 it's just example the values. I thought to calculate the walls position and length and also the cubes positions and length and then using padding and math.clamp to make restriction area.
In the script i'm getting the 4 walls sizes and also the 4 walls objects:
private int wallsLengthX;
private int wallsLengthZ;
private int wallsPosX;
private int wallsPosZ;
private int currentObjects;
private GameObject[] walls;
This is example screenshot of what i'm getting in some cases one some cube/s are partly out of the walls area: The right cube in the screenshot is part of it out of the walls area.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class SpawnObjects : MonoBehaviour
{
public int numberOfObjects;
public GameObject objectToPlace;
public Vector3 newObjectsSize;
public float spawnSpeed = 0.1f;
private int wallsLengthX;
private int wallsLengthZ;
private int wallsPosX;
private int wallsPosZ;
private int currentObjects;
private GameObject[] walls;
private List<GameObject> objects = new List<GameObject>();
private GameObject spawnedObjects;
void Start()
{
var wi = GetComponent<Walls>();
wallsLengthX = (int)wi.lengthX;
wallsLengthZ = (int)wi.lengthZ;
wallsPosX = (int)wi.wallsStartPosition.x;
wallsPosZ = (int)wi.wallsStartPosition.z;
walls = GameObject.FindGameObjectsWithTag("Wall");
spawnedObjects = GameObject.Find("Spawned Objects");
StartCoroutine(Spawn());
}
IEnumerator Spawn()
{
for (int i = 0; i < numberOfObjects; i++)
{
GameObject newObject = (GameObject)Instantiate(objectToPlace);
newObject.transform.localScale = GenerateRandomScale(newObject);
newObject.transform.localPosition = new Vector3(GenerateRandomPositions(newObject).x , GenerateRandomPositions(newObject).y + newObject.transform.localScale.y / 2.0f, GenerateRandomPositions(newObject).z);
newObject.name = "Spawned Object";
newObject.tag = "Spawned Object";
newObject.transform.parent = spawnedObjects.transform;
objects.Add(newObject);
yield return new WaitForSeconds(spawnSpeed);
currentObjects += 1;
}
var wp = GetComponent<WayPoints>();
wp.FindMyObjects();
}
private Vector3 GenerateRandomScale(GameObject newObject)
{
Vector3 newScale = new Vector3(UnityEngine.Random.Range(5, 100), UnityEngine.Random.Range(5, 100), UnityEngine.Random.Range(5, 10));
return newScale;
}
private Vector3 GenerateRandomPositions(GameObject newObject)
{
float paddingX = Mathf.Clamp(newObject.transform.localScale.x, 0, wallsLengthX) / 2f;
float paddingZ = Mathf.Clamp(newObject.transform.localScale.z, 0, wallsLengthZ) / 2f;
float originX = wallsPosX + paddingX - wallsLengthX / 2f;
float originZ = wallsPosZ + paddingZ - wallsLengthZ / 2f;
float posx = UnityEngine.Random.Range(originX, originX + wallsLengthX - paddingX);
float posz = UnityEngine.Random.Range(originZ, originZ + wallsLengthZ - paddingZ);
float posy = Terrain.activeTerrain.SampleHeight(new Vector3(posx, 0, posz));
return new Vector3(posx, posy, posz);
}
}
Answer by jeango · Oct 27, 2017 at 07:10 PM
I'm not sure I understand why you call GenerateRandomPositions three times to set the spawned object's position. I would say that's probably why you're having this problem, since it'll generate a valid X,Y,Z for which you'll only use the X, then you'll use a Y value of another generated position, and same for Z. So these three individual values are not guaranteed to position your object at a valid location.
try something like this:
Vector3 radomPos = GenerateRandomPositions(newObject);
newObject.transform.localPosition = new Vector3(randomPos.x , randomPos.y + newObject.transform.localScale.y / 2.0f, randomPos.z);
edit: Looked at your code a bit, and I don't really understand all the logic behind some of the things you do, so here's how I'd modify it
edit2: OK I now see what was the problem in your original code: when you calculate your random range, you should subtract your padding twice:
float posx = UnityEngine.Random.Range(originX, originX + wallsLengthX - paddingX*2);
My previous code didn't work because I was making a wrong assumption about where wallPosX was. Here's a cleaner way to do it. I'm pretty sure that solves your problem
private Vector3 GenerateRandomPositions(GameObject newObject) {
// first we determine how far from the center the object can be placed
float maxScatterX = (newObject.transform.localScale.x + wallsLengthX) / 2;
float maxScatterZ = (newObject.transform.localScale.z + wallsLengthZ) / 2;
// then we generate a random number based on that value
float scatterX = Random.Range (-maxScatterX, maxScatterX);
float scatterZ = Random.Range (-maxScatterZ, maxScatterZ);
// we apply the scatter to the center position
float posX = wallsPosX + scatterX;
float posZ = wallsPosZ + scatterZ;
// finally find y and return just like you did
float posY = Terrain.activeTerrain.SampleHeight(new Vector3(posX, 0, posZ));
return new Vector3(posX, posY, posZ);
}
It didn't let me a comment so i added it like answer. But now using the edited code it's creating the cubes on the top right half of it out of the walls area.
Answer by Chocolade · Oct 27, 2017 at 10:04 PM
I tried your edited code but now it's all the time creating the cubes on the top right and half out of the area: Each time i'm running the game it's creating the cubes in the same right top area and not inside the walls area.
This is the code now:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class SpawnObjects : MonoBehaviour
{
public int numberOfObjects;
public GameObject objectToPlace;
public Vector3 newObjectsSize;
public float spawnSpeed = 0.1f;
private int wallsLengthX;
private int wallsLengthZ;
private int wallsPosX;
private int wallsPosZ;
private int currentObjects;
private GameObject[] walls;
private List<GameObject> objects = new List<GameObject>();
private GameObject spawnedObjects;
void Start()
{
var wi = GetComponent<Walls>();
wallsLengthX = (int)wi.lengthX;
wallsLengthZ = (int)wi.lengthZ;
wallsPosX = (int)wi.wallsStartPosition.x;
wallsPosZ = (int)wi.wallsStartPosition.z;
walls = GameObject.FindGameObjectsWithTag("Wall");
spawnedObjects = GameObject.Find("Spawned Objects");
StartCoroutine(Spawn());
}
IEnumerator Spawn()
{
for (int i = 0; i < numberOfObjects; i++)
{
GameObject newObject = (GameObject)Instantiate(objectToPlace);
newObject.transform.localScale = GenerateRandomScale(newObject);
Vector3 randomPos = GenerateRandomPositions(newObject);
newObject.transform.localPosition = new Vector3(randomPos.x, randomPos.y + newObject.transform.localScale.y / 2.0f, randomPos.z);
newObject.name = "Spawned Object";
newObject.tag = "Spawned Object";
newObject.transform.parent = spawnedObjects.transform;
objects.Add(newObject);
yield return new WaitForSeconds(spawnSpeed);
currentObjects += 1;
}
var wp = GetComponent<WayPoints>();
wp.FindMyObjects();
}
private Vector3 GenerateRandomScale(GameObject newObject)
{
Vector3 newScale = new Vector3(UnityEngine.Random.Range(5, 100), UnityEngine.Random.Range(5, 100), UnityEngine.Random.Range(5, 10));
return newScale;
}
private Vector3 GenerateRandomPositions(GameObject newObject)
{
float paddingX = newObject.transform.localScale.x / 2;
float paddingZ = newObject.transform.localScale.z / 2;
float originX = wallsPosX + paddingX;
float originZ = wallsPosZ + paddingZ;
float posX = UnityEngine.Random.Range(originX, originX + wallsLengthX - 2 * paddingX);
float posZ = UnityEngine.Random.Range(originZ, originZ + wallsLengthZ - 2 * paddingZ);
float posY = Terrain.activeTerrain.SampleHeight(new Vector3(posX, 0, posZ));
return new Vector3(posX, posY, posZ);
}
}
hi, I changed the code of my answer a few days back. Did you try it? Did it solve your problem?
Your answer
![](https://koobas.hobune.stream/wayback/20220612142000im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
How can i prevent from mouse to collide with thirdpersoncontroller ? 0 Answers
How can i using a break point if a gameobject have a collider after added to it ? 1 Answer
How can i get all childs from List ? 3 Answers
How can i set the same script on two GameObjects so the script will work on both objects same time ? 1 Answer
How do i change the GUI.Box font size and box size ? 0 Answers