0
\$\begingroup\$

Consider a Spawn Area for GameObjects. We define a Spawn Area to be a boundary consisting of 3 or more points such that an object can spawn at any coordinate that is within the boundary of the Spawn Area. Contrast this with a Spawn Point, where objects can only be spawned at that specific coordinate.

In Unity, one method of creating such a Spawn Area is to place an Empty Game Object at a point, and then use Random.Range around that point.

Vector3 emptyGameObjectCoordinate = emptyGameObject.transform.position;
Vector3 randomSpawn = emptyGameObjectCoordinate + new Vector3(Random.Range(-1, 2), 0, 0);

My issue with this approach is that it is very difficult to visualize this area through the scene editor. It would look like a simple cube no matter what the area actually is.

What the area looks like in the Scene Editor

I have considered possibly using a box collider as the area. This is can easily be visualized.

Visualization of a Box Collider

However, Unity Lacks a method to select points within a collider.

It would be ideal if we had a method such as Random.insideCollider.

BoxCollider collider = GetComponent<BoxCollider>();

// Ideally. But sadly, does not exist.
Vector3 randomSpawn = Random.insideCollider(collider); 

So my question is, what is the Unity way of creating a Spawn Area such that it can be visualized through the scene editor?

As a bonus, how can we create areas that consists of arbitrary points, as opposed to just being rectangles or cubes? It would still need to be possible to visualize it, and it should be easy to select random points within it.

\$\endgroup\$
0
\$\begingroup\$

Gizmo and Handles class are your friend! Though it is for Editor Only, i think...

Make sure to read the docs carefully, as you need to make these call in OnGizmos() or OnDrawGizmosSelected() [Just like Update() or OnGUI()]

If you are looking for something that you can see in builds (Not editor) check out the GL class.

Bonus : The Debug class has a DrawLine and DrawRay function that might be useful.

.. There might be more new stuffs, but these are all I am aware of at the moment.

\$\endgroup\$
0
\$\begingroup\$

I was able to reach a solution using Albert's answer. However, I just want to go into more details with regards to my exact approach, as it may be useful to future readers.


Continue using an Empty Game Object to represent the spawn area. We will define the center of the spawn area to be equal to the Transform position of the Empty Game Object. We will then define the width, height, and depth of the spawn area to be equal to the Transform scale of the Empty Game Object. For simplicity, we will assume the Empty Game Object is axis aligned.

This means the coordinate selection logic should be as follows:

Vector3 origin = transform.position;
Vector3 range = transform.localScale / 2.0f;
Vector3 randomRange = new Vector3(Random.Range(-range.x, range.x),
                                  Random.Range(-range.y, range.y),
                                  Random.Range(-range.z, range.z));
Vector3 randomCoordinate = origin + randomRange;

Create a C# script that extends MonoBehaviour, and attach it to the Empty Game Object. This script will be used to add visualization to the Empty Game Object through the use of Gizmos.

Add implementation to the OnDrawGizmos() method to draw a cube at the Transform position, with size equal to the Transform scale. Notice that this matches our definition of the spawn area above.

public Color GizmosColor = new Color(0.5f, 0.5f, 0.5f, 0.2f);

void OnDrawGizmos()
{
    Gizmos.color = GizmosColor;
    Gizmos.DrawCube(transform.position, transform.localScale);
}

This will then draw the Cube only in the Unity Editor, but it will be invisible in game, which is exactly what we want.

Results of OnDrawGizmos()

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.