A Day About Changing Cars
The game I posted a few screenshots before, now complete!
A_Day_About_Changes_of_Cars.zip
And this is an extra cutscene, not included above
The game I posted a few screenshots before, now complete!
A_Day_About_Changes_of_Cars.zip
And this is an extra cutscene, not included above
Since any game needs some lore or backstory, I decided to make some.
This one is related to the game I showed at the end of this page, in the cutscenes editor section.
The shopping center's dome came down into a rain of shattered glass shards. The blaster agents came shortly thereafter, magnetizing the glass shards to their arms and then expelling them downwards, dampening the fall.
At the opposite side of the hall, the charge agents came through a similar route, but in a more awkward way. Zigzagging until they reached the ground, they came hitting and bouncing on every corner they could.
"Since when these Vero's thugs became so well trained?"
Ayane had several acquaintances in the northern state, and knew very well that it was made mostly of barren expanses and dotted with some villages. They barely had a police force, so it was inconceivable to her they could have a training center to come hovering that way.
"They aren't well trained." Hanzo looked at the red soldiers, civilians until two weeks ago. "Just as Zared isn't." and turned to their friend, attracting glass shards to his armor and shooting them at the enemy. "I think... these armors, all of them, are self-trained, and have some sort of specialized artificial intelligence."
"But the red ones are way faster with these shards."
"It seems our armors are more resilient, but theirs have a faster attack rate."
"Resilience shouldn't be enough for Zared keep standing there like a static target." and turned to him: "Come here, crazy!"
13 days from present, the day after the meteorite rain.
Ayane and Zared walked together at Fizo's condo.
"That looks like Fizo's house."
If Zared counted right, that should be the thirteenth street, Fizo's address. Ayane already knew very well the house's facade, and didn't count.
"Of course it is. It's the only automatic garage door that faces the street and opens outwards."
"Doesn't it block the other cars? And the neighbours, don't complain?"
"I think they don't know. Few people live here and most of them come just at the weekend. And if they knew, I think he wouldn't care about them." And completed on her thoughts: "Or about anyone else, really."
The two walked away from the main street, to Fizo's house. The house was now a pile of scattered debris and some standing walls.
"His place is one of the most affected."
"Divine providence, I guess."
"Stop hating."
"It's not hate. I just think he is a bad person."
Ayane turned the other way. "I don't want to dwell on that." and tried to find some other subject: "What are we supposed to find in this hodgepodge?"
"I guess we were supposed to arrive... and he'd be waiting for us. He commented something about an old green wallet and some clothe changes."
"Ok. So, I don't want to leave here too late. We can start searching it now and tell him if we find something."
15 days from present, near Earth's moon.
The Xzharians ships usually travel in fleets, but rogue exceptions happen. Bavrot was trying to correct this anomaly, talking rapidly in his native language:
"Any ship in this sector can hear me?"
The pilot consulted again his radar and verified that the screen remained the same: no allied Xzharian ships nearby, just some too far away to establish any meaningful communication other than presence.
What was near him was a menacing Verent fleet. They couldn't detect a Xzharian fleet so far away, but his systems could, pertaining to an exploration model that had better communications than most. And he knew that, if that was an elite Xzharian fleet as he believed, the barrage of fire would sweep him away together with all the other ships in the area.
"This is urgent. Somehow I fell behind a Verent fleet, and I can see there is a Xzharian squad coming. If anyone in the squad can hear, please hold fire while I evade."
Just silence. The evading maneuver started a hour before, and the pilot prayed that the elite squad wouldn't arrive before he was too distant to be a target. A firestorm wouldn't differentiate between a rogue ship or a ship taken by the enemy.
Bavrot suddenly became optimistic when a message arrived from the opposite side he was expecting. A relieving Xzharian voice was heard on the other side:
"We catched your signal from our moon base. Come full throttle to the location that I will transmit now. Don't worry. We'll intercept your ship for refueling."
Some happy thoughts crossed Bavrot's mind. On his nod, the auto pilot accelerated to the received coordinates, as it already had interpreted the operator's message.
He then languidly leaned towards the radar, the previous setting not disturbing him anymore.
Sooner than he expected the radar detected a Xzharian ship coming in his direction. How the one from the moon base could be so fast? However Xzharian navigation systems overestimated too much their pilots, and wasn't programmed to detect friendly fire.
The first missile hit the left propulsor, and others came afterwards. The ship was propelled, spinning relative to Earth and approximating it.
Bavrot tried to return to the evading maneuver, but after some minutes the planet's gravity caught it.
After much effort, Bavrot stabilized the ship. Other propulsors were just partially working, and he still couldn't avoid Earth's pull. He went to his next to best option, other than evading, and tried to find a landing site that'd give him chances to save the ship. He accelerated it until it became geostationary, hovering over a distant spot with a lake.
Fizo's House
Zared held the distorted piece of metal on his hands:
"These things aren't meteorites... More like parts of an engine."
The blue metal moved, and he dropped it on the debris pile.
"It is crawling on the ground?" Ayane looked to where it was moving: "Oh, my... And there are several of them."
"It seems they're going towards each other, doesn't it?" Zared moved a wood interloper. "But the debris isn't letting it."
Ayane was amused. It looked so harmless, so slow. She decided to take one of them on her hands and kicked some impeding debris on the others path. Zared silently reproved.
"What harm it can do? It will just turn into a big goo."
Ayane watched them group, morph and agglutinate. On her last kick, a thin stripe of blue metal sticked to her foot, linking it to the larger metal bubble.
The now single metallic mass crawled over her body and adjusted itself to make an armor vest. On the other side of the terrain, a transparent helmet quickly floated towards her and completed a full-body armor.
"Get away from me!"
Action followed words, and the transparent helmet floated back to the ground, the armor quickly receding to her feet, forming a cube by the helmet's side.
The artifact now resembled more a toy than a menace. She studied it, looked at all sides, moved it on the ground, and tapped it lightly. Nothing.
"Come back to me?"
Action followed words, and Ayane laughed. Zared was bewildered.
"Isn't that thing... dangerous?"
"Hmm... Yes, it may be. Better to take it off for now, right?"
Zared walked to the other side of the terrain.
"There is more of it here."
"Oh, jeez... no need to be jealous, I guess."
Iashita's Shopping Center
"I don't know why they're after us."
Ayane was concerned. Hanzo was more focused than having any discernible emotion.
"Our goal isn't to engage them... We just need to find the capsule and get away from here."
"And they're attacking us because of that capsule?"
"I don't know. It seems so. We found one in Vero, and it had the same inscriptions on the shell that this one, when it was falling." Hanzo asserted that Zared was holding them back. "We managed to enter it, but this same group shoot it from the outside. It became inoperable. It must be important, we just came here out of curiousity, and now they're attacking us." "I wish we can find it soon." "Seleca and Zeh already went after it. We can concentrate on just impeding their pass. It isn't such a challenge. We have worse attack but better defense. A zero-sum game... or a zero-zero game."
Fizo's house
"Look, I found it! His wallet! (Or whatever he calls this dirty bag.)"
It would have to fir Zared's backpack. Hers was already stuffed to the top with two blue cubes and two helmets, they almost jumping out of it.
"We can let one here and just carry one... We won't lose it, no one will search it here."
"I don't wanna come here again. You can use it, I can sell it... I can even let Fizo use it."
"I will call him to not come. We already found his wallet."
"And some clothes that no one can use."
Iashita's Shopping Center
"I know that I already asked this question before, but... where's Fizo? He could be helping here."
Ayane was going to say a few more things, or a lot of things, but Hanzo's intercom flashed and Zeh's voice was heard.
"Just received a message from the base. These aggressive aren't your everyday civilians."
"Don't tell me now Vero has a military academy."
"It seems there was a battle between a Verent fleet and a Xzharian one, near Earth... and several of the damaged ships was pulled by its gravity and fell on Vero and nearby here. A couple of large Xzharian frigates fell over a maximum security prison in Vero. It is the kind of prison that isn't for petty thieves. More like... serial killers, rapists, cruel murderers, leaders of criminal organizations... You name it."
Earth's exosphere.
It was worse than Bavrot thought. Not only his ship was falling on Earth's atmosphere, but the missile barrage caused a lot of Verent ships come alongside him.
One of them was too near, so near that there was no doubt that, if both pilots survived, a close combat would follow. Taking one last decision inside his ship, Bavrot set his ship towards the Verent one, and parachuted himself.
As he slowly fell towards the lake, his ship stroke the Verent one, both wedged together and falling towards a village nearby.
As both approximated the village, it was now the Verent's pilot turn to parachute herself. In a last attempt to save her ship, she targeted the only dampening place on sight: an automatic garage door opened, contrasting itself over the street.
Iashita's Shopping Center
A large metal pipe was propelled from the red team side and gyrated until it hit a pillar near the blue armors, taking a chunk out from it.
A voice soon was heard from their apparent leader, about what seemed a good strategy:
"Target the pillars!"
The volley of artifacts now was hitting all the columns at the blue team's front.
"Behind them!"
The pillars behind them started to crack. Or they retreated, or they would be trapped with fallen debris behind them and a falling ceiling in front of them. It didn't take much time for them to instinctively start stepping backwards.
The village at night.
Fizo turned his intercom on, as he walked away from his house's remains. He usually kept it off, unless he would call someone, to spare battery. There were several missed calls from Zared, so he called back.
"Where are... or where was you the whole afternoon? We found your wallet."
"I passed at my mother's house to take some things. It took more time than I planned."
"We also found some metallic things. It's like an armor... that also transforms into a cube."
"Like a trekking knight's backpack, huh? Yes, I also found one."
"Really? I thought we had scanned the whole place."
"Well, it was my house. I know how to search stuff on it."
"Anyway, Ayane brought two of these blue things on her backpack."
"Blue? I found a red one."
Iashita's Shopping Center
"The ceiling is crumbling all over the place." Ayane spinned her head following all the falling blocks and small bits, until she saw the corridor behind. A blaster was coming in their direction.
"Hey, hey, hey, whoa! It's me, don't shoot!" Fizo yelled in a breathless, broken pattern.
A large ceiling part fell behind him, and he jumped forward.
"Now that we're trapped you arrive."
"Don't worry, Fizo is here and will destroy them all. Just let me take some air... Ok, now I go."
He blasted one of the pillars near the opposing group and a flurry of bricks came flying in his direction. Being near, Hanzo pushed him to the side, absorbing the shock. "Don't advance this way! Your armor is like metal foil for this!"
The former hero fell backwards, unhappy by not being so decisive in the battle.
Zared looked at his friend's misery:
"What if we covered him?"
Hanzo considered the idea for a moment.
"It would combine attack and defense."
"Never thought I would say that, but... Let's protect him. Igloo formation!"
"Thank you."
"Just don't mess, and don't miss."
Iashita's Shopping Center, second floor, food plaza.
"Hey, Zeh! It is there, in the restaurant!"
Seleca thought the meaning of capsule was of something she could hold in her hands, but the large metal structure covered half of the restaurant's main room, the sunlight entering through the destroyed ceiling and bathing it all.
"Yes... Thanks goodness... Let's call the others."
Without further ado, Zeh ran towards the right corridor, Seleca following closely.
She turned the corner to the right corridor and found it blocked, full of fallen debris.
"These cracks and noise... it seems the fight intensified a lot."
"We can reach them through the other side."
Iashita's Shopping Center, entrance hall.
The longer path was quickly traversed, and as soon as they reached the corner of the battling room, they stopped to see the remaining members of the enemy team fleeing, several already fallen.
After them, Seleca saw what seemed to her like a... human tank. A blue metal shell moving slowly, with red arms appearing now and then shooting and disappearing again.
As the last red enemy escaped, and the next to him fell, Zeh yelled:
"Up here! We found it!"
Iashita's Shopping Center, Tulie's restaurant.
Hanzo and Zeh scanned each plate and etch of the dirty capsule's exterior. Occasionally they would sweep with their hands some dust or small stone away.
Zeh stroke a small embossed handle and pulled it, revealing a panel under it.
The others neared it, and Hanzo asked a question he already knew the answer: "These strange symbols, does anyone know how to read it?"
They looked at each other, expecting some answer from the others. Fizo opened his mouth and closed it again, Zeh muttered some question to herself and Zared shrugged. Ayane threw her hands up:
"Ok, no one knows how to read it..."
"There are buttons.", Fizo smiled. "What harm it can do? It is not like a weapon or anything."
"Maybe it can do." Hanzo worried from past mistakes. Ayane was more impatient: "So, we'll stay here forever?"
"Let's press some buttons."
The others silently approved or remained silent. Zeh looked at the symbols again, trying to link it to any proto-language she knew. She resorted finally to a more trivial method:
"Most of the buttons are yellow... Few of them have unique colors. Maybe if we just press the different ones, no default setting will be changed."
Hanzo was not certain on what to do. "You can try that."
She started pressing the ones with starkly different colors. On the second one, a previously invisible door made its boundaries clear. It lifted, until it was almost flipped upwards, and made the dark interior visible, as much as the light entering permitted.
At the first steps from Ayane and Hanzo inside it, blue lights turned on at the base of a central column. It was also possible to see a semi-circle of chairs, disposed around the capsule, opposing the door.
They all entered, and Fizo sat in one of the chairs.
"Huh... Not bad."
Hanzo eyes became wide open: "Look at your side..." Fizo jumped forward, seeing the chair's base illuminated. "Not only that, another light turned on at the chair's direction, above the column."
A few minutes later for some, a lot of minutes for others.
"There is some lights coming from inside the pillar too." Ayane looked around her, looking for someone to test it using two chairs. "Seleca, let's test it!" and pulled the friend forward, to the front of the same chair Fizo sit before. Seleca obviously was the best person to test it together, and she didn't mean it lightly.
"Alright... Let's test it."
As the two sat, the others attention was caught by an increasing glow inside the column.
"Whoa! It is working!" Fizo sat next to Seleca, and all followed afterwards.
The pillar became more and more luminous, until all became white.
A suspended passageway was extended in front of Fizo. It surely was a dream, as the imagery was surreal. The passageway was in the middle of a starred space, with no planets nearby, and Fizo wasn't wearing any space vests or breathing apparel.
Ayane stared at a curve far away, trying to discern if there was something supporting or holding the structure, but there was nothing for that purpose. As she called for her friends and there was no answer, she assumed she was the only one there, and started to walk.
Zared was still feeling the corridor was falling and would hit something at any moment when he raised his view, to see a myst growing ahead.
Zeh slowed down as a myst involved her, and continued walking. The myst became more rarefied, and she could see a crossroads facing her.
There were only two paths, with a gate on each one. Two planar openings that seemed to Seleca something like a misconfigured virtual reality game.
On the passage at right, like a full circle return, Hanzo saw the interior of the capsule he just left, with his chair empty, the others still sitting, eyes closed.
On the left, the view was very different, and more interesting. He could still see his five allies, but they were very distant from the previous battling scenario, at a gathering around a pool.
The nearest group to the gate was what made Hanzo feel a mix of relief and accomplishment. There was several fellow soldiers, that was also his colleages, all killed in an ambush by alien Tyors in a mission he led in the moon.
He was near enough to hear them asking why he was late, it wasn't everyday they could frequent a party like that, the illuminated cityscape sprawling around the apartment.
Fizo wondered how his allies made it there.
He noticed a familiar face, already oldened by the years, but that he still could recognize.
It was his father's, but that was more impossible than a connection between the capsule and that place. His father left his mother and him when he was seven years old, to never come back again or even send a message.
Ayane arrived afterwards, and commented he was helping their boy to finish his homework and would soon arrive. At this moment he noticed she was wearing a wedding ring.
He gave a slow step backwards, wondering how all that could be happening.
Fizo arrived with a boy that looked just like him. Ayane felt the impulse to enter the gate, but stood still and watched as he neared his father and sent the kid to look for her.
Zared saw the other five friends around the pool, and near to him, through the gate, was Alyssa, a childhood friend he didn't see since high school.
There was a friend by her side that he didn't know, but he's more interested on what Alyssa was showing through her unrolled intercom.
The intercom's enlarged screen showed several photos of a large farm while Alyssa swept it, one just like Zared wanted to buy someday. As she swept again, he saw the interior of a large living room. In one of the walls was a photo of him hugging Alyssa and three kids. She was indeed a long lost love he had. She swept the screen again, and more photos of the farm appeared, with robots plowing the land on the distance, and several tall posts with cameras and searchlights through the land.
Looking at the faces of all the people from her hometown, Zeh felt some of them she still liked, and most ranged from anger to bittersweetness.
In this category she put several people she admired, and it was painful to see them gradually ostracize her, after she moved to the small city's main streets with her girlfriend. This bothered her more than the veiled mockery other people did sometimes.
So it was odd that now they were all smiling, talking with Dri, greeting or hugging her sometimes. There was a banner with her name and Dri's, around a cake.
The two gates were very similar, as Seleca looked through them. The second capsule, on the left, had however its door opened and facing a tall building. Atop of it, she could see some of her friends and a table full with snacks and drinks. She still wasn't that hungry, but a lunch now wouldn't go amiss.
Fizo seriously considered entering the gate. So much so, that he went to the last possible place before crossing the border, and leaned towards it, but went back not accepting it as real.
A thunder resonated behind him and his attention was caught by it. He walked away from the gate, and runned away as several lightnings crossed the space.
The thunderstorm didn't distract Ayane. She stayed there, until her view started to blur and fade to black.
The six friends awoke together. Surprisingly, one of the red enemies was back inside the capsule, hitting the central column again and again.
He noticed they awaked and raised his arm, targeting one by one, until dwelling upon Fizo.
Ayane crossed the distance between then and jumped over the red enemy, all coming afterwards. Not much was necessary to subdue him, his head already covered in blood, from the previous battle. With a concentrated blast from Fizo and Hanzo, he became unconscious.
As Fizo recovered from the jumpscare menace, he turned to Ayane and almost said something, but paused, wondering what he could say: "I had a strange dream with two gates, and... my father was in one of them."
"I also had a strange dream with gates... but cannot remember details."
"All of us had a 'dream' about 'gates' like that?", Hanzo asked, and everyone replied nodding.
"It was quite good." Zared muttered, the others agreeing more discreetly.
There was silence for some time, until Hanzo returned to his next task:
"Alright! Let's see if we can remove this armor from him." He leaned towards the enemy, and noticed a small compartment attached to his waist. He opened it and there there was an intercom, still the last message displaying.
The message had an image with several locations and markings, and a text under it:
"We hit the jackpot this time. Take all of the capsules and make rental prices spike. Kill anyone that stays on the way."
Hanzo frowned. "I wonder what he saw in that gate."
Fizo laughed: "Fake stuff to profit from idiots, of course. If we had doubts whether it was real, they had none."
I made this animation tree some time ago for a sidescroller, and I think with some modifications it could be used in an autorunner:
And what is custom here and was premade by our virtual team? This is good to show, because this way it's easy to see how all the parts entangle together. I took the free model from the Unity Asset Store, and since it already comes with the models (several of them, with several different clothes) and animations, and that can be applied to any model, it is just to integrate the logic, and we're good to go. Not even customization is needed, as I will abstract the fact that the scene looks like space and we're not supposed to breath there.
The "logic" is not really code. It's a cool system that Unity calls Mecanim, that Unreal already had before, even in UDK, under the name of Animtree. This is an image of it taken from the internet:
As in autorunners we have to instantiate the modules the player will run over in runtime, randomly, this will be my next step here. The editor scene before play doesn't have much, just a skybox in an empty scene:
When I hit play, this is the code that instantiates it:
Not only the modules are random, but I can control what are the chances of they changing once I instantiate a new module. This avoids a scattered visual effect, and provides some uniformity.
When I hit play, the once empty scene changes, now with all the forty modules instantiated in runtime:
Later I will add curves, but before that we need the code that, as the player runs forward, new modules are instantiated ahead, and deinstantiated behind.
Here we have two options: or make the character go forward, or make the whole scene go backwards, like a treadmill. I will go with the first option, because, in the scope here, it can be more easily integrated with other scenes or maps. Here is it at runtime:
We have an early challenge if we want to use Global Illumination in runtime instantiated prefabs. The thing is: Unity doesn't do that. It makes sense from a common sense point of view: if, in GI, lights on each part of the scene affects the whole scene, there will be lighting seams, inconsistencies and contrasts all across the scene. And, because of that, Unity doesn't store baked lighting in prefabs. Even so, I think there should be an option to do that, if the developer wants it that way. Just a warning message and a click of Yes would do.
And, as I want GI on instantiated prefabs, it will have to be done manually, through the use of pooling, instead of prefab instantiation.
Pooling is when you activate and deactivate objects inside a scene, instead of creating and destroying. A drawback is that we are limited to a maximum number of simultaneous instances of an object in the scene, and an advantage is that it is faster than prefab instantiation at runtime. It is a lot used for bullets in rapid firing.
Here I won't use it because of performance, but just to not lose the beautiful lightmapping.
There were some other solutions on the internet, but it didn't work, so that will be the solution here. As a test, I baked the lighting in an instantiated prefab, disabled, moved and enabled it, and it didn't lose the baked lighting:
GI works only on static objects, but, as here I want things that look better but that still can be moved around the scene, I went with some unusual configuration: I marked lightmaps and reflection probes as static, and left the rest dynamic. So no optimization like integrating textures in batch processing, but still with all the more complex illumination:
The player itself is illuminated by a single direction light, using a culling mask that affects only him, to not saturate the already lighted scene:
Now there will be the next step: the pooling code to move, enable and disable prefab instances at runtime.
(4 hours later...)
This is the pool at runtime:
From the API client side, there is just a new class called PrefabPool with Get() and PutBack() methods:
And the actual PrefabPool code listing:
It has a nested class PrefabType, like a prefab that can be instantiated, but with a limited number of instances in it:
Later I will show the final implementation of the pool, adapted for the particular case of an autorunner, with additional methods to facilitate it.
At this moment, in the lighting part I alternated modules with and without ceiling to minimize global illumination inconsistencies, so that effects like radiosity are almost the same in any module:
Autorunner are a type of on-rails game, so now I will make an implementation of these rails. Before I show the technique I ended with, there were two others that didn't bring good results.
The first one was that the actual Transform of the character, i.e., it's position and rotation, would follow a very simple path of straight lines between different modules, with a trigger collider at the beginning of each module to inform the beginning of it:
To give a better sense of smoothness, just the character model, or image, would rotate continuously, despite the real movement being just a straight line between modules. This implementation however was not smooth enough.
The second technique had smoother results, but was more complex: the ground was covered with several mesh colliders, and each mesh collider contained a normal that informed the player the path forward:
And here is the path covered with these mesh colliders as guides:
This is a top-down orthogonal screenshot of the new curve, using straight modules as a background image to better orient it in Blender. The curve dimensions could be related with the straight module dimensions of 6.5x5x7, but wouldn't be essential. Settled with an arc with external radius of 50 and internal radius of 40, divided in segments of 15 degrees each.
As the data and calculations are mostly embedded in the scene, the code is straightforward, with the collider pivot being the new target:
And the one I went with was the more mathematical one, and the perfectly smooth one, to calculate the angular speed given the four corners of the curve. The curve now has snapped Transforms on each corner that are passed as parameters to a script in the curve:
And the code that makes the calculation:
It could be written in less lines, but I preferred to make it more descriptive and less obfuscated.
The script that uses this data is the forward script in the player avatar:
Autorunners are a randomized genre, and this one have hubs with openings in four directions besides curves, so from time to time the runtime generated tree will subdivide itself into three branches, and each of these can subdivide themselves, continuing this recursively untill all available modules are in the scene.
This presents some challenges not present in classic data trees: for one, as all trees, the best way is to do it recursively, but, different from generic data trees, if we don't inherit from MonoBehaviour there's several functionalities that becomes inaccessible to us, like a Destroy() on game objects. Another particularity is that, different from other trees, spatially two branches cannot collide with each other, so a different type of "branch prediction" is necessary. Therefore before each new module is added we need to know what are the module types that are allowed and what are preferred at that point to avoid future collisions.
The natural way of using recursivity on game objects is using a prefab that references itself, and, in theory, this should work, but in practice the prefab start to modify itself at runtime, and as soon as the root branch has three branches, it clones itself and each new branch is instantiated as a new four-branch tree.
The solution here was to put a different game object as the root, which sole purpose is to have a reference to the original prefab, and all branch prefabs instantiates new prefabs with this indirect reference:
As we don't know in advance which branch the player will choose, they grow mostly at equivalent lengths, so some guide colliders must go ahead on each branch, and be destroyed as each new hub is randomly generated, to give room to three new branches with three new guide colliders.
There are different ways of improving collision prevention, but ultimately multiple branches are just visual cues to hint at what is ahead, and the player always runs forward in a single path. So, if we discard the unpredictabilities that arise from performance and frame rate issues, an infallible way of preventing branches to never collide is to halt new modules to be instantiated until enough deinstantiations occur. Here, the worst case scenario is where the player crosses the last hub that gives access to the single path ahead and that is halted at the obstructed crossroads with other branches. As soon as the player crosses that hub, the other branches are deinstantiated, and only a single path ahead remains, unobstructed. The only drawback is that, visually, a temporary vacuum of modules occur, but that are soon filled up. A mist and temporary lack of obstacles could be a way to overcome it.
The tree is built by one instance of the class PlayerPathBuilder and several instances of the class PlayerPathBranch that instantiates itself recursively.
The root PlayerPathBranch is created by PlayerPathBuilder:
And all modules available at the PrefabPool are created inside the root PlayerPathBranch game object or one of the instances created under it:
After that, whenever the player hits a dequeue collider, it's time to deinstantiate behind, alternately choose one of the branches ahead,
and choose a new unobstructed module to instantiate ahead.
In the dequeue behind stage, if the hit was on a hub dequeue collider, it's time to make the chosen branch the new root branch and discard the
other two branches and all other branches under them:
The following enqueue ahead stage is handled inside the PlayerPathBranch.Instantiate() called above. Besides getting a new module from the unhindered types and instantiating it at the end of the tree, it also does some clean up, as having a minimum of modules between each hub, and instantiating curves instead of straight corridors when this distantiates the branch from collisions. If a hub is randomly instantiated, then it's time to create three new branches under it and from now on alternate adding new modules between these branches, the same way it instantiated the hub because it was reached as the bottommost branch in the tree:
Here are the complete code listings:
And some screenshots and a video of these in action:
In indie game development, especially garage indie, not alternative studio indie, it is very common to take free assets online and customize it to your own needs. After all, that is our virtual team. So in this section we will see some customizations that were made for the autorunner game, and some more customizations for another game, a follow-up sci-fi game.
Part of level designing is to lay out several variations of game assets across a scene, and build a cohesive whole from these parts. But, for that, first you need the modules themselves, in a way that they can be easily and neatly integrated with other modules in the scene.
To show some techniques for that using Blender, let's modularize some parts of the Corridor Lighting Example found in the Unity Asset Store. The modules I used as straight paths in the autorunner, as well as parts of the curve modules, were taken from that.
When a package wasn't meant to be used as modules, more often than not it comes as the opposite of that, in an amalgamated lump of meshes, materials and textures. In these cases, the first step has no visual effect, and it is to organize all these parts in different folders, in a preparation for modularization.
Here we have the original corridor lighting example, grouped by type, and then the listings for the hub prefab and the straight corridor prefab, grouped by module:
You can notice that, in the second and third listings, there is a folder named "_Unused". In both cases, they contain the original model. Part of modularization, as we'll see later, involves separating each mesh into several parts.
Sometimes what seems symmetric actually isn't. For example, in the hub here, it was made to always have two open doors and two closed doors, so there was no need to be symmetric. As I wanted that it was a hub that could have any doors open or closed, and traversed equally well in any direction, I made the floor and the texture symmetric in all four directions.
It is good practice to have a standard for module sizes in a game, so that they can be easily snapped together. In the Corridor Lighting Example, it was very straightforward to do so, as the dividing gates between modules were the sole joint that needed to be redimensioned.
In this case, I settled in the dimensions of x:11; z:11 for the hub, and x:6.5; z:7 for the corridor, all with a height of 5 units. To snap two modules seamlessly together is easy: just move it by one of the external gate corners and snap it together to another external gate corner.
You may have noticed in the previous picture that one of the corridors was wider than the others, and that is the main goal of dividing the meshes inside each prefab: to be able to rearrange them internally to make new module variations.
Here it is highlighted how the mesh was divided to achieve this double wide effect:
In the step above, I made a new module just using separate parts of a previous module. This can be used in several ways, but if you want to rescale just some parts while stacking others, it can can happen some distortion in the horizontal or vertical stretching of corners.
Here the door frames were rescaled, while other parts of the modules were just stacked. Besides the corner distortion, these modules were made just to be seen from the inside, so whenever there is an opening, we can see they're thin like a paper sheet.
To correct that, we can go for Blender and separate the corners, making it possible to scale just the horizontal and vertical parts of the frame separately, and also solidify all the parts, to make it irrelevant if they're being seen from the outside or inside.
Another common asset to handle in games are spacecrafts, and in this case we want one that can be massive, wreckable, and also house some nested prefabs on it.
The Corridor Lighting Example was developed by Unity Technologies themselves, and the Stratos Class Cruiser was made by Ruslan Nazirov, and also taken in the Unity Asset Store.
Early on, our first item in the wish list is that the ship needs to be massive, but Unity's maximum texture dimension is 4096. So, to not have jagged textures or use tiled ones, I broke the texture and the object into several ones, and remapped the UVs. As a side goal, the ship also became wreckable into these parts.
In the previous section, in the UV mapping screenshots, I skipped the next to the last object, called "Top.Middle.001.transparent" in the Blender file. This is the glass window that will begin opaque and end transparent at the end of the camera orbiting.
In the material settings window, the rendering mode is set to "Fade":
In the next section we'll see a way to implement a script-based parser for cutscenes, but before that, as the game is comics-influenced, I need some comic balloons for it.
For that, I will use GIMP to edit some comic balloons from the internet that remind a bit of mangas. You can download the comic balloons files here for free, all you have to do is to credit Starline/Freepik, as described in their license.
Transparencies in Unity is a bit of an agreement between parts, as not all formats save alpha channels in a way that Unity understand as such. Also, if you're used to other photo editing software like Photoshop, GIMP is a bit different and has some type of a learning curve. So, although in the game I ended using this technique for other comic balloons, this illustrates how it can be done with GIMP.
If you are already used to other editing software, the steps are very straightforward, and this is how they translate in GIMP:
Cutscenes are ubiquitious in console games and each time more present in mobile games. So, now we will see how it was implemented in a game with cutscenes in the beginning and the end.
The parser is feed with binary data from a custom script editor, that saves into the application's data folder.
Each data file is separated into chapters, or nodes, and each node has components that contain the commands and parameters to be parsed and sent to the right objects in the scene.
And these are the beginning and ending cutscenes of a game that uses this architecture: