Hen Avrami
Hen Avrami

Reputation: 17

How can i spawn random objects that are not overlap between specific given area?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WallsTest : MonoBehaviour
{
    // using a GameObject rather than a transform
    public GameObject prefab;
    public Vector3 wallsStartPosition;
    public float width = 0;
    public float height = 1;
    public float length = 2;
    public Camera wallsCamera;
    public float wallsArea;

    void Start()
    {
        wallsCamera.transform.position = new Vector3(wallsStartPosition.x, wallsStartPosition.y + 100, wallsStartPosition.z - 235);

        BuildWalls();
    }

    private void Update()
    {

    }

    void BuildWalls()
    {
        for (int i = -2; i < 2; i++)
        {
            GameObject go = Instantiate(prefab);
            go.transform.parent = transform;
            Vector3 scale = Vector3.one;
            Vector3 adjustedPosition = wallsStartPosition;

            float sign = Mathf.Sign(i);
            if ((i * sign) % 2 == 0)
            {
                adjustedPosition.x += (length * sign) / 2;
                scale.x = width;
                scale.y = height;
                scale.z *= length + width;
            }
            else
            {
                adjustedPosition.z += (length * sign) / 2;
                scale.x *= length + width;
                scale.y = height;
                scale.z = width;
            }

            adjustedPosition.y += height / 2;
            go.transform.localScale = scale;
            go.transform.localPosition = adjustedPosition;
        }
    }
}

For example the length is 100 so the area will be 100x100 i think. And i have the wallsStartPosition for example 250,0,250

Now i want inside the walls area to instantiate at random position number of objects. For example 50 cubes. But they should not be overlap each other and for example the minimum gap between each other should be 5. and maximum gap as fas it can be.

But i don't understand yet how to calculate the area and position of the walls and just instantiate random objects inside.

And this is the script for spawning gameobjects at random positions in given area. In this case the area is the terrain. But i want the area to be inside the walls i create in the first script. This script is attached to the same empty gameobject like the WallsTest script.

Another problem with the SpawnObjects script is that there is no any set for the gap between the objects and if the objects too good like scale 20,20,20 some of the objects that spawn on the edge half out of the terrain.

spawn

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnObjects : MonoBehaviour
{
    public Terrain terrain;
    public int numberOfObjects; // number of objects to place
    private int currentObjects; // number of placed objects
    public GameObject objectToPlace; // GameObject to place
    private int terrainWidth; // terrain size (x)
    private int terrainLength; // terrain size (z)
    private int terrainPosX; // terrain position x
    private int terrainPosZ; // terrain position z
    void Start()
    {
        // terrain size x
        terrainWidth = (int)terrain.terrainData.size.x;
        // terrain size z
        terrainLength = (int)terrain.terrainData.size.z;
        // terrain x position
        terrainPosX = (int)terrain.transform.position.x;
        // terrain z position
        terrainPosZ = (int)terrain.transform.position.z;
    }
    // Update is called once per frame
    void Update()
    {
        // generate objects
        if (currentObjects <= numberOfObjects)
        {
            // generate random x position
            int posx = Random.Range(terrainPosX, terrainPosX + terrainWidth);
            // generate random z position
            int posz = Random.Range(terrainPosZ, terrainPosZ + terrainLength);
            // get the terrain height at the random position
            float posy = Terrain.activeTerrain.SampleHeight(new Vector3(posx, 0, posz));
            // create new gameObject on random position
            GameObject newObject = (GameObject)Instantiate(objectToPlace, new Vector3(posx, posy, posz), Quaternion.identity);
            newObject.transform.localScale = new Vector3(20, 20, 20);
            currentObjects += 1;
        }
        if (currentObjects == numberOfObjects)
        {
            Debug.Log("Generate objects complete!");
        }
    }
}

Upvotes: 0

Views: 2175

Answers (2)

Dev Oskii
Dev Oskii

Reputation: 929

You can use Physics.OverlapSphere to test if two objects are overlapping. This assumes that the objects both have colliders.

Once you test this condition and it evaluates to true, I would suggest simply moving the object that overlaps and testing it again against the other objects in the scene. You can get clever with this by only testing objects you think might be close to overlapping, or overlapping.

Alternatively you can just compare every object to every other object in the scene. This would not be ideal if you have a lot of objects, because doing so would be O(n^2) complexity.

In any case you can use this function to test overlapping. Good luck.

hint: if you make the collider bigger than the object, you can place items a minimum space apart. For example if you have a cube of localSize 1,1,1 - the colider can be 5,5,5 in size and Physics.OverlapSphere will return true if the colliders overlap, demanding that the cubes be a certain space apart from each other

Upvotes: 0

STRIPE
STRIPE

Reputation: 1

My technical knowledge is limited, but you'll have to either get the script to spawn these objects every [X] amount of position ("posX += 1.0f;", or something to that effect) so that they appear in a uniform manner, or, have the script record each new object's position and use that information to calculate space away from said objects to spawn another one.

In any case, depending on the end result you're aiming for, you'll have to write how these objects operate in a given space. For example, if you have a messy room as a scene, you can have one desk that would find space in the corner of two walls, one bed alongside one wall and rubbish spawning randomly.

Upvotes: 0

Related Questions