When it comes to the background, classic shmups usually use something like infinite scrolling. Because we are not making a normal shmup with spaceships and other flying stuff we wanted to handle this completely different.
Therefore we created a static background, which is not moving during the actual battle. To give the user some feedback regarding progress, we also move the background after defined waves or a boss fight.
To avoid creating hundreds of full sized background assets we thought of randomly create these backgrounds out of a tileset image.
This is actually quite easy, the only thing you need is a image with a defined grid of single tiles. Next thing you will need is something to draw the tiles on. I used the unity plane component with a mesh renderer for that.
First step, initialize the mesh:
int numTiles = size_x * size_y;
int numTris = numTiles * 2;
int vsize_x = size_x + 1;
int vsize_y = size_y + 1;
int numVerts = vsize_x * vsize_y;
Vector3[] vertices = new Vector3[ numVerts ];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];
int[] triangles = new int[ numTris * 3 ];
int x, z;
for(z=0; z < vsize_y; z++) {
for(x=0; x < vsize_x; x++) {
vertices[ z * vsize_x + x ] = new Vector3( x*tileSize, 0, -z*tileSize );
normals[ z * vsize_x + x ] = Vector3.up;
uv[ z * vsize_x + x ] = new Vector2( (float)x / size_x, 1f - (float)z / size_y );
}
}
for(z=0; z < size_y; z++) {
for(x=0; x < size_x; x++) {
int squareIndex = z * size_x + x;
int triOffset = squareIndex * 6;
triangles[triOffset + 0] = z * vsize_x + x + 0;
triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0;
triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 3] = z * vsize_x + x + 0;
triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 4] = z * vsize_x + x + 1;
}
}
// Create a new Mesh and populate with the data
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
// Assign our mesh to our filter/renderer/collider
MeshFilter mesh_filter = plane.GetComponent();
MeshCollider mesh_collider = plane.GetComponent();
mesh_filter.mesh = mesh;
Next step, split your background image into single tiles:
private Color[][] SplitTiles() {
int numTilesPerRow = texture.width / tileResolution;
int numRows = texture.height / tileResolution;
Color[][] tiles = new Color[numTilesPerRow*numRows][];
for(int y=0; y < numRows; y++) {
for(int x=0; x < numTilesPerRow; x++) {
tiles[y*numTilesPerRow + x] = texture.GetPixels( x*tileResolution , y*tileResolution, tileResolution, tileResolution );
}
}
return tiles;
}
Final step, draw your random tiles on the mesh:
int texWidth = size_x * tileResolution;
int texHeight = size_y * tileResolution;
Texture2D newTexture = new Texture2D(texWidth, texHeight,texture.format, false);
Color[][] tiles = SplitTiles();
for(int y=0; y < size_y; y++) {
for(int x=0; x < size_x; x++) {
Color[] p = tiles[Random.Range(0, 30)];
newTexture.SetPixels(x*tileResolution, y*tileResolution, tileResolution, tileResolution, p);
}
}
newTexture.anisoLevel=1;
newTexture.mipMapBias=0f;
newTexture.filterMode = FilterMode.Point;
newTexture.wrapMode = TextureWrapMode.Clamp;
newTexture.Apply();
MeshRenderer mesh_renderer = _plane.GetComponent();
mesh_renderer.sharedMaterials[0].mainTexture = newTexture;
With a shader on top the final result looks like this
Download Unity 5 Sample Project
As with every previous tutorial, we provide you with a sample project for Unity 5.