Tantramantra and the magic of design

Good spring day!



During the development of various mechanics and other interactivity for computer games, various recipe schemes are formed to implement the required functionality. Most of them are not tied to the specific engine / language used. I will tell you about some of them using the example of one of my projects with biomachines.







Tantramantra



First, about the project itself. This is a test range of several map-worlds, where you can ride a biotransformer machine that can jump, somersault, strafe and create some objects. Also, the controlled vehicle is able to switch into various forms, including those that are sharpened for flight (do not have wheels).



On the maps there are teleporters (blue star-shaped objects) that carry the car to other worlds. There are four such worlds in total - the starting one, with water and rocks, with a flat surface, and one more watery.



In the starting world, the player quickly begins to pursue two terminators, who can be defeated with the help of special weapons (after which they can ride in a more relaxed atmosphere). If they turn out to be more agile, then a game over occurs and the game starts over.















Design of game mechanisms



Usually, the user, including any game, does not even really think about how everything is arranged inside (even if the developer is playing, you still need to tune in to a certain way in order to perceive what is happening more analytically). Interaction just happens, everything happens by itself. In a word - some kind of magic, although it seems to be relatively familiar. Plots, heroes, narrative - this is all superficial (although not insignificant from a different point of view), since the player is able to drive even abstract cubes across the screen, simply because β€œclick, click, go,” he has already been hooked and carried. At the same time, the game does not have to be cerebrospinal - shifting cards, clicking different switches / switches and other measured activities just also catch the user with their feedback, because it just is.



Questions like "why does Mario break bricks with his head" are not at all what worries the player in Supermario. He plans to jump into which pipe, how to break the block and catch the mushroom in time to kill the annoying cloud. In fact, this is a solution to various problems presented in the form of symbols and in-game relationships. Symbols, of course, trigger associations, so along the way you can discuss with those around you bricks, plumbers, pipes with flytraps and other psychedelic going on (which actually does not happen, it's just probably a more abstract and interesting topic than discussing some boring household things).



Actually, a person is able to come up with some kind of abstract entertainment for any reason literally out of the blue, whether it is expressed in counting crows, photographing, looking at passing cars, in some mini-challenges, like being in time somewhere or preferring to do conditional file instead of going to the service center. That is, there is no history, just an activity, even if it is mental, and the whole interaction consists at least even in filtering the incoming information (what to pay attention to, what to ignore, and so on).



So, although the in-game action is perceived by the user at the level of fairly obvious events that happen (clicked that, took this), completely different stories take place behind the screen, from which you only need to make the right impression. And to be and to seem are two different things.



The task of game design is precisely the selection of a specific model that will allow you to create the desired interactive. The ways of solving these problems can be quite different, but quite often it is possible (and necessary) to look for the model that will simply form the desired illusion, without unnecessary complications. That is, you do not need to connect the text output plugin if you only need to show a couple of labels, and it is enough to display a picture with them. You do not need to include a physics library if all physics in your game is simplified gravity by moving the object downward in each frame. And so on and so forth.



Sometimes it works the other way too - when there are already some built-in tools, the same physics, then why not do some things through it. The same timer can replace a trigger cube falling from a certain height. The player will still see only what they have decided to show him and will perceive the connections between objects that the developer has formed for him.



Coming up with the structure of various laws and connections in play in the game, you need to break them down into separate elements, for a start, at least highlighting the primary and secondary functionality. An elephant should still be eaten in parts, even if it's not an elephant at all, but let's say ...



Mushrooms



For some time, the "mushrooms" in the prototype were a decorative element, but it was immediately implied that later they could at least be crushed. Thus, they needed the following functionality: tracking collisions with the player in order to hang some kind of reaction on it. As minor details: a more visual effect of destruction, as well as replacing the actual destruction with the transition to an inactive phase and restoration of the fungus after some time.



As a result, collisions with mushrooms are determined through the use of the engine's proposed WorldTrigger element, which reacts to intersections with geometry.







All mushrooms are packed in local prefabs. The IntersectionMask parameter, which sets bit masks for intersections, is not used in the mushroom code, since it was needed for raycasts.







: Enter. Update , « ». «» . Enter, , «».



β€” , , , .




If there were no prepared tools in the form of triggers and rays in the engine, then it would be possible to write your own version of collision calculation. For example, it is banal to consider the difference in coordinates between a mushroom and a typewriter. And since special accuracy is not required, then this process can also be optimized in various ways, for example, to check the distance along only two axes, and at the preliminary stage to watch only one, connecting the check to the second when necessary. That is, each "mushroom" in the cycle could check if the car's position by X is within its range, and if so, then check the range by Y and make some decision further.



Terminators



The game required some elementary pursuing enemies. I decided not to make them wheeled, creating some simple spheres that move in a simplified way.



Thus, it was necessary to plan the following: the implementation of a rectilinear movement, movement towards the player. The secondary tasks here were: the possibility of shooting and some kind of additional polishing of the movement.



It was possible to make the enemies physical and move them with the help of forces, but in order not to complicate things, I wrote them a non-physical movement, regulated by raycasts.







And here is how these enemies are arranged - a pair of spheres and a dummy sight, into which shots will spawn.







, . . . , , ( ) . , .







Cars already knew how to shoot all kinds of gizmos, but those were various special effects - physical cubes, glowing spheres, and so on. To inflict damage, I wanted to have a separate pickable weapon with cartridges, like in shooters. First of all, so that the player more clearly understands when it is possible to shoot with something that produces a real effect. You could also go to another option - hang up the shooting on specific vehicles so that the player can switch to destructive forms at any time.



The weapon had to: a) raise, b) shoot. This is when viewed from the player's perspective. Well, from the point of view of the developer: a) somehow establish a collision of a weapon with a typewriter, b) decide how exactly to display what the weapon is received, c) determine the rules by which the weapon is used. As you can see, the shots themselves were not even a priority in this way. Largely because the spawn itself by a typewriter of directionally moving objects had already been prepared and it only remained to attach it to the sale of weapons.







The pickup point also uses the WorldTrigger to detect collisions.







. . . , newWeapon .



An object containing a model of a flying cannon is placed on the level and turned off. In case of a collision with the point of selection of weapons, it turns on this object and it flies to the player under the influence of its control script, and then follows the player further. At the same time, the car goes into combat mode (one of the important switch flags in the code changes) and in this changed state everything that previously happened with the left mouse click is replaced with weapon shots. When the cartridges run out, the machine itself turns off the object with the weapon model and returns to normal mode.







NodePet - an object representing a cannon







NodePet. , , -, . Rotator β€” , , , ( , ).

β€” , . X Y, Z .

, . , , .










Actually, the shells themselves. To begin with, I gave them to the terminators in a simplified form, without causing damage, and when they already worked as needed (including already writing off health from the car, displayed in the interface) and the mechanics of the weapon being picked up were also ready, then it came to the player's shots.



These shots work a little differently.







Fragment of the enemy shots script. They appear and begin to fly in the direction where the terminator was looking (that is, at the player). The shot does not start firing additional actions immediately, but after a short delay (reactionTimer) - a simple way to avoid any unwanted collisions at the point of its appearance.



, - , , .



- RigidBody, .



, .



, - , «». , .








. RigidBody . , . , .



, . , , , . , , , .



Thus, it is much easier to damage the terminator - it is more open to hits, but it is difficult for the player to aim from his straight-line weapon, so the enemies also have some chances.




Electricity grid



Some machines had the ability to water the space in front of them with physical cubes. And at one fine moment, a game mechanic came up with which these cubes could interact - it was supposed to be a small chain of deactivated "power plants" that can be repaired by throwing them with the same cubes.



It required the preparation of the station, again tracking collisions, some kind of mechanism for showing the progress of the repair and determining other related details. This time, a PhysicTrigger was used with a mask set only for specific cubes.



I decided to display the construction progress with cubes of the same color, placing them in circles at the base of the station and turning them off. When a cube hits a station trigger, its physical body is turned off (the visual cube itself continues to hang for some time, as if it has fallen into a certain field), and the station shows one of its cubes until everything is filled. As soon as this has happened, then a glow appears at the station and a connecting line is extended to the previous station. In addition, each station contains a link to the next one, which must be made active. And instead of the very last, a teleport to the water world is turned on, which is initially inactive.







Several cubes are scattered near the first station to be repaired, as some hint of the desired action from the player.



Demo version



Below is a video cut of the gameplay from the fresh version of the prototype 01_02





The archive with the demo weighs 714MB. It runs on 64-bit Windows and is available for download on the itch.io page (the Unigine engine is used, so the system requirements are not the smallest):



thenonsense.itch.io/tantramantra







More pictures













All Articles