We are a team of four people comprised of university students and full-time workers and sadly overestimated the time we could invest in this Challenge. Nonetheless, we do like our ideas and design and would like to share what we have so far with the community. We had the idea specifically for this challenge. While brainstorming what cool and innovative things we could do with the new 2D tools we came up with the idea of making real-time deformable Sprite Shapes our core gameplay feature. After some feasibility testing and playing around with the possibilities went relatively well we stuck with the idea. Next, we had to decide how we wanted to implement this feature and after throwing around some ideas we stuck with using Lense-like effects to affect the game world.
Marco Strobel Game Design, Gameplay and Feature programming
Alexander Giesbrecht Game and Graphics Design, Level building
Fabian Büntig Shader Design
Daniel Trabitzsch Sound and Level building
2D Features used in the project
With our decision to work with real-time deformable sprite shapes we started to think of all kinds of distortions, also outside of the scope of sprite shape deformations. First ideas for puzzles and levels were scribbled down and we started to get the first basic idea more and more into shape. Below are our first ideas for various kinds of deformations, including projectiles that can be made smaller or larger to gain an advantage in gunfire, a lens that can change the size of the protagonist and a lens that can freeze water. During this initial brainstorming, we filtered through the list of lenses and decided to implement 2 of them for our first prototype.
With the basic idea for the usage of the 2D tools, we thought about the story and setting of the game. We wanted to somehow integrate the typical 2D view that is used in 2D side-scrollers into the story and came up with the idea of a drone that flies in a certain distance to the scene to capture it. That idea also helped us to anchor the lens that is used for the level distortion. After the decision on the drone that carries the lens and observes the environment from a distance, we came up with the rest of the story fairly quickly. Our game plays in a post-apocalyptic world caused by a war between humans and machines. The machines developed a technology which allowed to manipulate natural objects by the use of lenses that distort anything that is occluded by the lens. Humanity took heavy blows by that technology and having no chance to stand up against the machines, decided to flee into a computer simulation by leaving their bodies and loading their consciousness into computers. The world was emptied of human beings in physical form and riddled with various secret facilities in which computers, the new homes of what is left of humanity, are stored. Ironically these computers are maintained by machines and drones themselves because their programming was forcing them to fight flesh and blood, not lifeless objects. The times passed until one day on which a human from inside the simulation managed to hack a maintenance drone and gave it the task to find a human body, hoping that a lifeless body won't cause conflicts with the drones programming. The drone heads out of the facility and searches for a tool to fulfill its task. After searching in different places, it finds a frozen worker robot in a storage facility. From here on the journey of the drone and the robot begins.
The controls are that of a classic jump and run/side-scroller. The A and D keys control the left and right movement respectively while the Space bar lets you jump. The camera is a Cinemachine Virtual Camera and follows the player robot. Furthermore, you control lenses that are attached to the mouse cursor and can have different effects on the environment. You can cycle through these lenses via the mouse wheel. More on these lenses in the next chapter.
Core Gameplay Features
Lenses are our tools for interacting with the environment outside of the robots simple movement controls and physics. They can affect objects inside the world and the robot itself as long as these are seen through the lens. We have a list of ideas for different lenses, however, for this demo, we have implemented 2 of them only. The lenses can be switched any time and can be categorized into active and passive lenses. An active lense is triggered when needed and also consumes energy, however, energy consumption is not yet implemented. An example of an active lens is our heat lens, which can heat up natural objects. A passive lens does not need to be activated, nor does it consume energy. An example of a passive lense is our distortion lense that radially pushes out objects. In our demo, we can distort the ground to create elevations or crevices that are needed to overcome obstacles.
Distortion Lens - Modifying the Landscape
The Distortion Lens distorts the landscape behind it and pushes deformable elements from the center towards the outer radius of the lens. This is an example for a passive lens which means it does not consume energy and has to be activated by the left mouse button to come in effect.
We currently use a dense distribution of statically set control points on SpriteShapeControllers to create more smooth looking deforms. This comes at the cost of performance. We have optimized this so the scene runs with a constant 90+ FPS on our machines and we are looking into replacing this approach with a more dynamic one in which additional control points are only placed when and where needed.
The deformation process works as follows:
When the lens trigger collides with a SpriteShapeController its Spline is further analyzed and if any control points are within the radius of the lens they are modified by a modular deformation delegate function. This can be used to apply any deformation logic we want and easily experiment with new formulas. The delegate takes the points original position as well the current deformed position and with access to all the lens attributes returns a new deformed position for the point. With the current demo lens, this calculates the vector between the lens center and the control point and normalizes this vector to the lens’ radius thereby pushing it towards the outer border of the lens. This is used as the Target for a Lerp between the current deform position and this newly calculated position and returned as the current deform position. We have looked into other deform formulas but this has been the best for our puzzle scenarios so far.
A SpriteShapeController modified this way then has its BakeCollider method called to update its collider. This is not the most efficient approach but it works in our target boundaries. We will look into improving this in the future as well.
There are rare problems of the character falling through the landscape collider when modifying a SpriteShape, the robot is standing on, too fast. This is due to the robot suddenly being on the other side of the SpriteShapes collision edges with no physics frames in between. We mitigate this problem by increasing the raycast length for collision on our character controller as well as gradually modifying the SpriteShape towards its target shape instead of doing it instantly.
With our dense and complex spline approach, we noticed a few problems in Unity’s toolkit. For one the SpriteShapes sprites seem to be tiled between control points which means with every additional control points it’s not a continued smooth sprite but more of a broken tiled look. The other is that with more complex spline shapes BakeCollider seems to create a lot of duplicate collision vertices. We are mitigating this by iterating through the points list after BakeCollider has finished and removing any sequential duplicate Vector3 from the list. This collider post-processing helps increase performance by a lot.
Heat Lens - Modifying Temperature / Melting and Burning things
The Heat Lens increases the temperature of any temperature sensitive element behind the lens. Temperatures have a normalized range of -1 to 1. This is an example of an active lens which means that it consumes energy and is only in effect while the left mouse button is held down. Currently, this lens is used to gradually melt away ice that is blocking the way when it gets over a temperature of over 0. Other barriers in the level like a tree start heating up and burning away once it hits high temperatures.
You also have to be careful to not accidentally overheat the robot which happens when it reaches a temperature of 1. In case the robot overheats it will shut down and be uncontrollable until it has cooled down again. At the beginning of our first level demo, the robot is stationary and frozen in a cooling chamber. You can’t start controlling the character until you bring it up over a temperature of 0.
Objects that are affected by low temperatures gradually get a blue tint on their Sprite when they reach low enough temperatures while objects reacting to high temperatures start getting a red tint in the opposite scenario.
Every element that can react to temperature changes starts listening to temperature events once it starts enters collision with the Heat Lens and they all can react to temperature changes in their own unique way.
Future levels will have temperature zones in which an object’s temperature will be modified while entering and staying in these. For example, a cooling chamber in which the robot would slow down with decreasing temperature until it freezes in place and the player has to get it through while regulating his temperature without running out of heat energy.
Conceptional Lenses and their possible use cases
As you can see in our earlier concept scribbles we thought about all kinds of different Lenses that affect the world in different ways and while we focused on just the simple push-outward distortion and heat lens for this submission we are planning on bringing a lot more unique lens mechanics in the future.
Some of the lenses covered by our concept scribbles are different kind of distortion lenses, also adding the ability to redirect the trajectory of projectiles with them and puzzles like Donkey Kong Country-esque mine cart rides where you’ll have to manipulate the tracks to make jumps or get through barricades in a more time constrained manner.
Further puzzle ideas involving the Heat Lens like lighting torches to see or starting a fire to scare away animals/enemies.
Additional lenses cover a snow globe like lense that basically acts as the opposite of the Heat Lens and freezes things, a fishbowl like lens that lets you carry water and fish around and a noise lens that can turn the robot or objects into particle clouds and let you pass otherwise impassable barriers.
In order to visualize the lens, we wrote an image effect. We wanted to show that the lens has an effect on the whole environment even on the parts it can not directly interact with. Since we have several ideas for different lenses we wanted to design the image effect as modular as possible. The shader takes the current position of the lens or mouse as an input value and calculates a mask. The mask is rather simple since our lens has the shape of a circle. We use this mask to limit the image effects to the size of the lens and to adjust parameters of the lens like the softness and maximum values.
The distortion effect transforms the UV coordinates in the from center of the lens to the current pixel position. When we sample the main texture (camera image) with these coordinates we get the effect that the pixels are pushed out from the center of the lens.
For the heat effect, we created a fractal-sum noise texture and use it to distort the UV coordinates. In addition to that, we use UV-scrolling in the v direction to simulate a heat distortion effect. Furthermore, we tint the image with a color gradient to further emphasize the temperature difference.
To decide on our visuals, we looked into different 2D games for inspiration and in conclusion liked a hand-painted style with clear black borders. The environment was planned to be constructed by the 2D tools tile maps and sprite shapes. Objects to fill the environment were planned to be painted in a modular way so that level designers can build environments with variety. The first asset that was created in that style was the desert tree shown below on the left. Once the tree was done, we realized that it takes a lot of time to paint with that level of detail and that we would not be able to finish our prototype level that way. We decided to create much simpler assets as shown on the right with the intention to replace the assets with high-quality ones at the end.
We pursued the goal to create an environment that consisted of different regions like a desert region, an urban region, a forest and a facility. Again our goals did not go well with our available time and we reduced the environment to the desert region and constructed a level that starts inside the underground storage facility in which the drone finds the robot. Below is the entire prototype level sketched out to give an overview of the different level sections.
As the robot finds its way up and out of the facility, it finds itself in the desert and comes across a dam that it needs to cross. After a while, a tree blocks the way on a narrow passage. After overcoming the tree, a big industrial pipe chases the robot down a slope. Once the robot manages to save itself, our prototype level is finished. We tried to design the level in a way that requires the lenses to move on without giving away the solution to quickly, however that was harder than we imagined and our puzzles are probably a bit to easy. Once the concept for the level was done we started to implement this level in unity. Most elements are sprite shapes, as they are very easy to use and allow for very fast generation of level segments. Also, most floors are made of sand and by that are deformable so sprite shapes were the only choice in most cases anyway. The background of the lab was done with tilemaps. Once a palette was prepared, different sprites can be simply painted onto the grid. That way the underground level was painted quickly.
In the end section where the pipe is rolling down the slope and we have to run away from it, we used the NodeAttach script found in the Unity tutorials on the 2D Sprite Shape. With the script, we attached the steel poles to a control point of the underlying sprite shape so that the pole can be pushed out or into the sand.
Some of the background elements outside were done with sprites, some with sprite shapes. The sand dunes for example are painted elements that are assembled to create a background. Next are some images showing the most important sections for comparison to our concepts shown above
For the robot we wanted to use elements of actual humanoid robots with some sci-fi influence. Our design is inspired by the robots made by Boston Dynamics, which is probably very obvious. This style emerged in the first concepts and we continued working with this. The robot was then painted in a disintegrated state with all the limbs separately spaced out. The arm and leg that is in the back were painted a bit darker so that there is a distinction when the robot is animated.
For the setup of the robot, we made use of the 2D rigging tool. The robot was painted in its individual parts and then rigged and weight painted in Unity. The overall process is very much like typical character creation workflows and with that easy to learn. In the process of painting the skin weights, it was cool to see that additional vertices can be added to areas like the rubber so that these areas can be animated as well.
Once the character was standing on its legs, we gave it life by making use of the 2D IK tool for the animations. We used 4 effectors for the legs and arms by which we could make the robot run. In the left picture, the effectors are indicated by red spheres. We managed to implement 2 animations, one idle and one run animation. With these animations we could cover the most important states of the robot, namely when it moves or when it does not move. Due to limited time we did not make a jump and fall animation.
For the head, we wanted to have something that indicates an eye or a sensor that scans the environment. For that, we created a sprite animation which shows a rotating laser.
We used Cinemachine to keep the camera following the robot. In general working with cinemachine proved to be very easy and it takes a lot of work of your shoulders. We did not implement anything fancy with this tool, however, it was still nice to save some time for other more pressing things. Another very important element in game design is the sound. Unfortunately, we did not have the time to implement a lot in that regard. To create some atmosphere we used a darker tone in the underground facility that fits the dark surroundings. As soon as you see the first rays of light penetrate the darkness, you are welcomed onto the surface. In the entire surface section, we used an ambient desert soundtrack that fits the scenery in our opinion. The tracks that we used were not made by us and are published under a free license. Also we wrote some scripts, like the elevator scripts or a level reset system including checkpoints. These elements are however no 2D tools so we did not describe them.
The prototype that we managed to develop can be seen in the video. It shows a complete walktrough of the level.