PLAY HERE! http://tume-maailm.pri.ee/ylikool/CGP/2020/fall/Sprash/
HTTP BUILD! has to run in http server: https://mega.nz/file/7OJBAQLQ#X3z_0lK4xCBavqeD06UYCX1SrCxeLLM3hDhuNQQzkZM
How to play
Use "WASD" keys to move, use 1, 2, and 3 for abilities.
Sprash is an Asteroid-like game 2D game, where instead of shooting and dodging asteroids, the player has to navigate and fulfill objectives amidst a storm of space debris. The game will feature multiple levels with different environments and challenges. The end product has custom satellites, cool abilities, and different themes or satellite skins.
During this semester, I want to create a prototype or a vertical slice of the game. The game will be 2D, but in some instances, I want to use 3D graphics. Sprash is my first Unity project, so I will be learning that as well.
My plan this semester:
- Implement a dynamic environment with moving obstacles. Obstacles are in this case space debris or small rocks that can damage the player.
- Obstacles can break into smaller obstacles on impact. If the obstacle is big, then it can split into multiple smaller obstacles.
- Player has multiple abilities to interact with the environment. Someone suggested a net, but the abilities may also include thrusters, which boost your speed, or magnetic shield, which will deflect small debris from the player.
- Have some objectives on the map. To complete the level, players have to fulfill their objectives. This might be to use some ability in a specific circumstance, survive X amount of seconds, etc.
- Make the game beautiful. The game is happening in space, it should be apparent from the graphics, debris should shine if it is metallic, etc.
I am doing this project with my friend, Umesh. He is responsible for all non-technical aspects of the game. This means that most of the design and all of the code will be done by me.
Milestone 1 (25.09)
- Set up a scene with movable satellite and static obstacles (4h)
- Script for debris (4h)
I added a satellite (a white box at the moment), asteroids (a placeholder asteroid sprite), and a background (a placeholder starry sky).
I also created a script for generating new asteroids and the asteroids will disappear when they are too far from the satellite. This functionality has to change a bit because when the satellite moves away from the source, the number of asteroids near the source becomes very dense. Also, the satellite is faster than the asteroids, so if moving away, it becomes empty. The solution would be to create asteroids in the direction of the satellite movement.
The collision was also added.
Milestone 2 (9.10)
- Make asteroid generation better (make objects in direction of movement, object pooling) (2h)
- Make asteroids 3D (3h)
- Make the satellite 3D (1h)
- Research about the asteroid/debris splitting (2h)
For 3D asteroids, I create a low polygon count icosphere with random vertex displacement using a vertex shader. I am using a mesh collider, although I believe that the mesh collider uses the original icosphere mesh as its base. The solution would be to apply the heightmap during the creation of the mesh. I made the satellite 3D also but it looks just like before: a square.
In the game view, I am seeing a strange bug. Whereas the asteroids in the scene view are smooth, in the game view they are pixelated. I tried changing the LOD but it did nothing.
Also made generation better. The semicircle where they spawn is now shorter since on the very edges the asteroid density was very high. Asteroids are also generated in the direction of the movement.
Regarding breakable objects:
The most common technique is to have the object be composed of many smaller fragments. Then each fragment has its own physics, so they collide with each other. There is also a AddExplosionForce function under Rigidbody, which seems useful. Blender has a Cell Fracture function, which will generate random cracks.
Milestone 3 (23.10)
- Create procedural asteroids with breakable sections (5h)
- Model a simple satellite (1h)
- Model simple space debris with breakable section (2h)
The simplest way that I can think of is to create a tessellated 3D shape, then skew the vertices randomly. There are many options on how to tessellate 3D space.
I have decided to implement the one above since every face is the same (a diamond shape). You can read about the shape here: https://en.wikipedia.org/wiki/Rhombic_dodecahedron
Construction is easy:
My first attempt was a failure:
There were multiple problems I found. Firstly, the vertex shader was still enabled, which means that the vertices had random offset, making them all random. Secondly, the light source was (0, 0, -1), so it was hard to see different triangles. After the fixes the result was this:
The reason for the dodecahedron not fully rendering was backface culling. Some of the triangles were facing in the wrong direction. Here I got it working:
Although they looked boring on the 2D camera:
With some transformations it looked more interesting:
With fixed lighting:
The next step was to put multiple of them together. First attempt:
Clearly the offsets were faulty (one was almost detached) and they were inside each other. On top of that, the generation was (and still is) really slow!
After removing the transformations (that make the asteroid bumpy), we get this:
This is much better. I concluded that the problem was the transformation. Namely, the random seed was not the same. The seed calculation was faulty: in a way, I added the coordinate offset twice to the seed input, making it mismatch. After the fix:
The breaking was also implemented:
I also added some space debris. Unfortunately, it is not breakable yet, but the game object is composed of separate meshes, which will, in the future, break off on a collision. Also, it can be seen that the collision does not happen all the time. That is because the debris also moves in Z coordinates (even though the position is frozen in that axis!).
Finally, I also update the satellite model. It is hard to see with the default material, so I changed the material on one of the faces:
Milestone 4 (06.11)
- Fix bugs introduced in the last sprint (2h)
- Optimize the asteroid creation algorithm (3h)
- Create materials for the new models (4h)
- Add particle effects (1h)
I took an algorithm for anisotropic reflection from here and ported it to HLSL. Here is the result with torus:
But with a surface it looks really boring:
Tweaking with the light direction, it seemed to me that the highlight is just too big to fit on that small surface. When I changed the roughness constants, I produced this:
After adding the brushed texture (with Simplex noise) and fixing bugs (the tangent vector has to be rotated when the object has been rotated since everything is calculated in the world space) the result looks like the following. I am happy with the result:
For solar panels, there were few options. One of them was just pure black, which would be easy to implement but not very interesting to look at. The option that I like is blue with lighter streaks. Here is a reference:
I used the UV coordinates of each face to determine which color the pixel should be. I also added Blinn-Phong shading. Unfortunately, anisotropic reflection can not be seen due to the light direction. I have to figure out later how to get the reflection and illuminate the panels (and other non-metallic components) at the same time. In theory, the panels should act as mirrors.
I implemented a 'skybox', which is actually just a plane with procedural stars. Then I used the same algorithm to generate a 'reflection':
Instead of a specular, the sun should be seen instead (since it is a mirror). Here is some experimentation, although it looks like a moon. Also, stars should not be reflected if the sun is visible (since they are too dim compared to the sun).
I will continue with the solar panel material when the satellite is able to rotate. Then it is much easier to test it.
I also added the materials to the debris:
And finally, I added some particle effects. It still has to be modified (for example, use a cooler texture):
Milestone 5 (20.11)
- Improve particle effects (2h)
- Implement satellite rotation (2h)
- Implement two abilities (4h)
- Improve materials to work correctly with rotation (if there is time)
I update the particle systems in two ways. Firstly, I attached it to a separate game object, which does not move, but can be moved. This way, when I 'move' my satellite, the particle system can move in the opposite direction (since the satellite is always at vec3(0, 0, 0)). Secondly, now I am using a dodecahedron mesh for the particles, with custom material. The lifetime is 2 seconds.
The satellite can now also rotate. I used a coroutine to make the animation smooth. It is apparent that the aluminum parts do not act the same when rotated (no anisotropic specular highlight). This has to be fixed in the shader by taking into account the normal in the local space. Then the roughness vectors have to be rotated so that the highlight could be seen. To move to the next side, press "r".
A shield ability is now usable. It is on side 3 and can be activated by pressing "1". The activation just enables a game object which consists of a sphere and a sphere collider.
I created a simple missile object which uses a trail renderer component to draw the exhaust.
For the missiles, I created an item pool, so multiple rockets can be active at the same time. I also created a targeting system, where you can tell each frame what point in space to target. I tested it with a constant target (vec3(15f, 15f, 0f)) and this is the result:
Looks like the rotation is shifted by 90 degrees :D. I fixed it (a bit). Then I took a random Debris class object and targeted it:
Milestone 6 (04.12)
- Improve missile visuals and seeking logic (2h)
- Add an objective and a way to fulfill it (2h)
- Add UI (3h)
- Final refinements
- Make a build
I improved the missiles a bit. First iteration:
The rotation is still a bit buggy. Also, sometimes the missile explodes right away. The particle graphics are not that great either.
The rotation was fixed by setting Rigidbody velocity instead of position. The instant explosion was fixed by only allowing collisions between missiles and colliders named "AsteroidMesh" and "PanelMesh". This means that asteroid breaking colliders and other missiles will not cause explosions.
Next is UI. The main goals for the UI are to a) show what ability is currently selected and is usable and b) show the objective.
The abilities are shown as thus:
When the ability is not selected, it is faded out.
Camera ability was added as well. The UI will show the direction and area of the objective:
When the satellite enters the circle, the camera ability can be used to complete the objective.
- Add noise to missile trail particle effects
- Add color to missile trail particle effects
- Multiple objectives
- Something in the background
- Camera lag maybe