Alpha 5 is out! That took less time than I expected. And, I've changed the name from the probably-stupid "The cubes are breathing" to "Polyhedra"! You can play it
here. Any feedback is much appreciated!
Alpha 5 Changelog- Added randomized weapons
- Adjusted enemy level scaling factor (gets more difficult more quickly now)
Now, onto what you all really care about - the guns! I was originally going to just have a bunch of prefab gun parts that could be stuck together randomly, but my friend
@ignifluous suggested re-purposing the random mesh generation code that I use for the enemies to make the weapons. So, that's exactly what I did. As such, this will sort of serve double duty as a primer on how I generate the enemy models and the weapons.
First off, we need a class to hold the attributes for the weapons. These play into both the final stats of the guns, and also how they look. That data is stored in a class called WeaponAttributes, which has three variables - speed, weight, and accuracy. Speed is the fire rate of the weapon, weight determines the damage, and accuracy doesn't do anything yet but I'm working on it.
Now, the actual mesh is generated by first creating an empty GameObject and deciding how many cubes the model is going to be made out of. This is done by getting a random number between 4 and 4+(10 - weapon.speed). This means that faster guns have fewer cubes in them. Then the magic happens.
for(int i = 0; i < numCubes; i++){
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.localScale = new Vector3(Random.value * weapon.weight, Random.value * (weapon.accuracy + weapon.weight), Random.value * weapon.weight);
cube.transform.parent = gun.transform;
cube.transform.position = new Vector3(Random.Range(-0.2f, 0.2f) / weapon.accuracy, i * gun.transform.localScale.y, Random.Range(-0.2f, 0.2f) / weapon.accuracy);
}
Basically, we create a bunch of cube primitives, then set them to random sizes. The x value is the width, the y value is the length, and the z value is the height. This means that higher-damage guns are bigger, while lower-damage guns are smaller. More accurate guns are also longer. After that, we simply set the positions - the x and z coordinates are mostly random, but get less variant the more accurate the gun is. Each cube is placed a a certain distance from the last, so you don't get guns that are just one giant cube. Or, at least, you usually don't get guns that are one giant cube.
After that, we use Unity's handy CombineMesh feature to fuse all the bits into one mesh, to cut down on draw calls and make a few things easier.
MeshFilter[] meshFilters = gun.GetComponentsInChildren<MeshFilter>();
CombineInstance[] combine = new CombineInstance[meshFilters.Length];
for(int i = 0; i < meshFilters.Length; i++){
combine[i].mesh = meshFilters[i].mesh;
combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
meshFilters[i].gameObject.active = false;
}
gunMeshFilter.mesh = new Mesh();
gunMeshFilter.mesh.CombineMeshes(combine);
Then we set the material to a random color, and add a component to the finished gun that holds its damage, fire rate, and accuracy.
The stats for the guns are made by first generating a random damage value between 1 and ten, then calculating the fire rate with the formula frt = (10 - dmg) + Random.Range(-1f, 1f). This makes it so that high damage guns have a lower fire rate, and low damage guns have a high fire rate, with some random variance in there for flavour. The accuracy is just a random number form 1 to 10 until I figure out exactly what I want it to do.
And that's it, really. I doubt that this will be useful to a ton of people, because I don't know how much demand there is for scripts that generate random, vaguely gun-like shapes made from cube primitives, but I hope it was interesting. Thanks for reading!