Part 26 - Refining the Game - Part 3.
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...
Then I built a cube...
And manipulate it to fill the rough volume I want the coins to spawn into.
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
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.
- Part 01 - Installation
- Part 02 - Concepts
- Part 03 - Navigation
- Part 04 - Git and Unity
- Part 05 - Building a project
- Part 06 - Adding some plugins
- Part 07 - Creating some objects
- Part 08 - Physics
- Part 09 - Pushing things & animation
- Part 10 - Pushing coins
- Part 11 - Custom Scripting
- Part 12 - Spawning things
- Part 13 - It is still too fast
- Part 14 - Coins are piling up
- Part 15 - Materials
- Part 16 - User control
- Part 17 - Keyboard input - Fire
- Part 18 - Keyboard input - Movement
- Part 19 - Deleting Coins
- Part 20 - Walls
- Part 21 - Adding a GUI
- Part 22 - Adding the GameController
- Part 23 - Scoring links with events
- Part 24 - Refining the Game - Part 1
- Part 28 - Slowing the user down
- Part 29 - Some more changes