Part 26 - Refining the Game - Part 3.

By Jamie Chatterton / 2018-06-12

Now the fun thing…

There are no coins on the game at the start!

We need to spawn a load of coins at the beginning of the game.

I'm going to try and make this easy, by using a cube to define the volume in which to spawn the cubes, and a script to spawn them.

Starting from the initial view...

Open this image in a new tabInitial view
Initial view

Then I built a cube...

Open this image in a new tabBuild a cube
Build a cube

And manipulate it to fill the rough volume I want the coins to spawn into.

Open this image in a new tabThe InitialCoinSpawner
The InitialCoinSpawner

I've named the cube InitialCoinSpawner

I've added InitialCoinSpawner as a script too.

I've also made the cube a child of the spawner to keep the spawing objects together

Open this image in a new tabMake child of spawner
Make child of spawner

Once we have this we need to do the code to make it do all the calculations of where to spawn the coins.

The Unity API exposes the bounding volume of a mesh. So we can use this to calculate the extent of the cube we just added and calculate where to randomly place coins. We also need to know the size of the coins to make sure we don't place the center of the coin at the edge of the cube and therefore overflowing outside of the cube. We could decrease the size of the mesh by ½ the size of the coin, but if we ever change the coin to something else, we'd have to change this too. Might as well add it to the calculations too.

Now. There are two ways to get the bounding volume of the Mesh. Via the Mesh directly, or via the Component that renders it. Asking the mesh is a little wrong. The mesh works in its own space and can be very different to the World space. The Renderer component works in World space and will be the same, expected, values as we see in the Scene.

I'm going to dump the code from the InitialCoinSpawner and then explain it….

public class InitialCoinSpawner : MonoBehaviour {
   public GameObject spawnObject;
   public int numberToSpawn = 50;
   public Transform spawnContainer;

   private void Start() {
       gameObject.SetActive(false);

       var cubeBoundary = GetComponent().bounds;


       var temporarySpawn = Instantiate(spawnObject);
       var spawnBounds = temporarySpawn.GetComponent().bounds;
       var size = spawnBounds.size / 2.0f;

       var spawnMinimum = cubeBoundary.min + size / 2.0f;
       var spawnMaximum = cubeBoundary.max - size / 2.0f;

       Destroy(temporarySpawn);

       for (var i = 0; i < numberToSpawn; ++i) {
           var position = new Vector3(
               Random.Range(spawnMinimum.x, spawnMaximum.x),
               Random.Range(spawnMinimum.y, spawnMaximum.y),
               Random.Range(spawnMinimum.z, spawnMaximum.z)
           );

           temporarySpawn = Instantiate(spawnObject, spawnContainer);
           temporarySpawn.transform.position = position;
       }
   }
}

To start with we need 3 publicly exposed attributes that we can access in the Unity IDE.

spawnObject will be the item we are going to spawn, the coin in our case

numberToSpawn will allow use to control how many we spawn at the start, so we can fine-tune it.

spawnContainer is the Transform object that will be the container of the object, just so we can spawn them to the same place as the other coins. This is going to be the spawn object in the hierarchy. Essentially the immediate parent of the InitialCoinSpawner.

Ultimately we could've made it so that this Cube object was an object that the script pointed to, and the script was in the spawner and pointed to the Object that defined the boundaries, but I went this way around instead.

The Start method is where all the magic happens.

To start with we immediately deactivate the object. We don't really need it. It's just a placeholder.

We then get the full boundary of the object, in World Space, using the Renderer.

We now need to create a temporary instance of the spawnObject. If it doesn't have an instance it doesn't report on its boundaries, so we need to create a temporary one to find this out.

Again, using the Renderer, we discover it's bounds object, but this time we use it to find the objects size.

We move in the boundary of the cube by ½ of the size of the object, this is to make sure when we create an instance of the spawned object, its edges will only go up to the edges of the cube at most.

Destroy the temporary object.

Finally, create numberToSpawn instances of the spawned object, positioning it randomly within the calculated extrema, making it a child of the spawnContainer.

This looks like this

And is roughly correct.

Git repository: https://bitbucket.org/hiveit/unity-tutorial-coin/src/022_AddingCoinsOnStart/

I've changed a few options in the game.

The odd coin was falling through the floor object. I think this was due to the multiple collisions forcing overlapped coins to not work correctly. It appears as though turning on "Interpolate" in the coin prefab "Rigidbody" has fixed that, but it was intermittent and may crop up on occasion.

The coin prefab also had all the 'Static' options removed. This was mainly the shading, but it looks better.

I put the InitialCoinSpawner in a "Hide" layer I created. This is so I can hide it in the scene view and it doesn't get in the way of viewing the coin pusher in the scene.

More posts in this series.