Nick Carlson: A Level from a Developer’s Prospective

Hello everyone, I hope you have all had a wondrous week! I have spent the last week building Data Thief’s Tutorial, specifically the narration and final touches of the level. I wrote, and recorded dialog that will help immerse the player, and teach them the basic mechanics of the game. Despite our usual list of bugs, I was able to create a narration system, that handles when to play and stop clips.

In my system, a parent object (which I named “Nick”) has an audio source, and a queue that holds audio clips. The child objects each have their own trigger colliders  that call functions that either queues audio clips, clears the queue and plays a clip to interrupt, or simply stop all narration. The parent object also has an array of audio clips, so that other scripts may call a function that uses an int index as a parameter to queue clips from that array.  This audio system seems to work well in our game, and I tried to make it as robust as possible, so we can change or add any features we need in the future.  When the player unlocks and goes through each door, the narration queue is cleared, and if an interrupting sound is attached, it will play that, and queue the next bit of narration.

Level1DevView.PNG
This is a development view of the tutorial level. Each of the green wire frame boxes is a collider that interacts with the narration system.

I had some extra time to move around the main menu scene, and create a few more info panels. I also created and textured a door, as play testers were wondering if the main menu room was built around the player.

This slideshow requires JavaScript.

Thank you for reading, have a great week, and be sure to check back next week!

Advertisements

Caliber Seraphim: Switching it Up

It’s never good enough, is it? This weeks implementation comes with the ability to switch between different colors of lasers, which was a core mechanic. Originally, the effect was two-parts, where the color would bloom out for the active color, and then pull in for the now-inactive color. Due to a limited understanding of the render order and stenciling in Unity, this was the best effect available. But it’s not good enough? A few hours of work later, a new effect was born. This effect nullifies other colors while inside the mask of one color. It’s a bit more complicated than that shader-wise, but not by much. In total, about 28 shaders were born to create the following suite of effects.ezgif-3-7d02e2505d

Nick Carlson: Bugs, Blogs, and Blue Screens of Death

Hello Everyone!
This first week  of our third month has been a chaotic roller coaster, as it seemed like every task I attempted had at least 3 setbacks. One example: several different game objects with sound effects became unattached from the master volume mixer that I made a while ago. This made it so our build had random objects with really loud sound effects, while other effects and  the music would be quiet.

Most of my time was spent designing levels, and working on an info panel on the previously unused monitor in the main menu. This screen displays the controls of the game by default, but the player can click the arrows to cycle through other helpful tips. I also set this up so we can simply drag an image into an inspector slot to add it to the array of information panels. I made these images myself in GIMP, with a little art help from my teammates.  There are currently only two panels on the screen, one for controls, and one for color combinations. If you have any suggestions for information to add in the future, let me know!

This slideshow requires JavaScript.

The biggest, and most recent set back I’ve had is that I tried to update my laptop to the newest version of Windows 10, and now it randomly gets the blue screen of death (Bsod) at random all the time. Luckily I was able to get all my work onto a flash-drive, and set up my personal gaming machine with Unity, so at least I can work on there for the time being.  I think the drivers of our laptops aren’t compatible with the newest version of windows, as I’ve tried uninstalling and reinstalling my graphics card drivers several times, but it still blue screens randomly.

I’ve also spent a lot of time writing asset request documents, and communicating with artists. We’ve also recruited a good friend of mine, who is a web developer, to help set up a  promo site for the game, and maybe even a blog. I’m very excited with the direction of Data Thief, and I can’t wait to have an official website, and prettier development blog.
I hope you all have a great week, make sure to read my teammates posts, and  to check back next week!

Jorge Castaneda: Get Ready For An Overhaul; End of Month 2

On the last week of Month 2 I took an adventure through refactoring code to add a feature and solve a bug. For those unaware refactoring is the act of going back to old functioning code and rewriting it to make it better in some quality. This could be performance, code could be running too slowly, or modularity, the code may depend on too much other code and therefore be unable to be reused, or maybe to overwrite old functionality, getting rid of/ replacing old code that is no longer needed, or various other reasons. In this case it was both for performance and to overwrite old functionalities.

The Bug:

I identified a soft error that was preventing the merger from activating when hit by certain lasers. The merger was ignoring specific lasers. So I tracked down a commonality between these lasers. It turns out they all had the same identification number. Since they were all saying they were the same laser, the merger was ignoring the copycats. This all came from how Ids were currently being adjusted. The Ids were being incremented in every new laser with the exception of splitters which were adding 100 and 1000 to the other two lasers it produced. in that case when you sent a laser through a splitter and those into two other splitters an over lap occurs between the laser that get 1 and then 100 added to it and another laser that gets 100 and then 1 added to it. That is problematic. Thankfully there was functionality I had already planned to add that could be used to solve this issue. Object pooling.

Pool Parties and performance:

An Object pool is a system for adding some early processing to ease future processes. There is a cost to instantiation, the creation of objects and their associated components. Every time you instantiate the computer has to build an object from scratch add all its components and run all of its starting code, and fill all the variables with preset values. This is a costly process. The more components and the more child objects an object has then the more cost in making it. Now in a normal setting what most do is just instantiate objects when they are needed. This is actually fairly optimal if the instantiation is only required a few times per scene. However in the case of objects that you know will be instantiated and destroyed constantly this is not optimal. Like in the case of our lasers. However there is a good work around for this poor performance. Object pooling. A process akin to recycling. First at the beginning of a scene you estimate the number of an lasers that will likely be in the scene at a single time. Then you instantiate that many lasers from the get go and you store them out of sight and inactive. Then when you need them you distribute them from the pool to place they are needed. When they normally would be destroyed instead you return them to the pool. The cost of pooling is simple: the cost of creation is taken early on but less objects are created in total.

Squashing the Bug:

Now that the laser pool is created how can it help with that bug from earlier? The issue was that lasers did not have unique identification. This was because we were making the lasers as they were needed and then assigning them ids based on the previous laser’s id. However with the implementation of a laser object pool the lasers were no longer being created. They already existed. This means that they could all have unique ID’s assigned to them before any laser transform uses them. Therefore making it impossible for id overlap to cause issues.

Overwriting Old Functionality:

So you have an object pool and an old implementation that doesn’t use it. Its time to overwrite the old functionality that creates, destroys, or changes the Id of a laser (since that would defeat the purpose). Unfortunately for me that was a massive overhaul but while I was at it I refactored some of the code that was less then favorable. Like the splitter was way larger than it need to be and unwieldy when it came to choosing the color each nozzle will fire. As well as fixing an earlier bug when rotating a splitter when there are 3 lasers. I basically told the rest of the group not to touch and laser related classes for a day and a half. However it worked almost immediately.

So that is how I solved a game breaking bug as well as upping the performance of the game. I am pretty happy with this last build of the month.

Caliber Seraphim: 3/2

Week 3 was mostly bug fixes and polish in preparation for our demonstrative expo. Most of my work has be inclusion of features to further polish the game. I implemented my lava lamp shader in a lamp on the menu, corrected bloom profiling issues (which caused issues with players seeing objects) and performed some material color collection. In addition, I refined some features (namely, increasing alarm countdown time when inside a laser) and added in a scoring system in preparation for Steamworks integration.ll

Data Thief (Public Alpha 0.1.14) can be downloaded at this link.

Jorge Castaneda: The Curious Case of the Laser’s Edge

This week has been dedicated to edge cases and paranoia. A common issue developers have to deal with is the edge case. An edge case is a certain game state that causes an error. It does not happen all the time. Its not necessarily uncommon though. The more complex the amount of things that affect an output the more edge cases can occur that have to be accounted for.

A design choice that at this point we cannot undo because all our systems revolve around it is the mono lasers  one and done implementation. Lasers are the most common object in our scene. As such making all of them constantly update would drastically effect the running speed of our game. If each was constantly running ever laser would be ray casting at all times. this would cost performance but also insure that collisions are constantly correct. Lasers would be stop at objects the player holds in the way. Currently that doesn’t happen. Very early on I ran into an issue with making the laser continue through the checkpoint. I wanted to make it continuous but Activate only got called the first time it hits anything that has an activate function. This was a critical junction. I had designed all the other laser transforms with the expectation that they would only need to know when a laser hit them the first time, Activate, and when a laser stopped hitting them, Deactivate. Unfortunately I made the wrong decision. I made it so Activate is called every time the laser hits a laser transform regardless of whether or not it was already hitting it. I did not quite understand the consequences of that choice until now.

The consequences is that for every new laser transform I create I have to handle the edge case of a laser moving only slightly withing the hit box of the transform. This means a lot of extra if statements that I did not know I needed. These issues did not come up until we tested in VR and some weirdness kept occurring that I could not figure out for the life of me. When i was testing on my own computer using some Unity Editor code to expose functions directly so I could test them I was not having this issue. It makes sense that I would miss it though. After all I was directly changing the angle to where i wanted it instead of changing the angle of a laser in small increments. Small enough increments to hit the same transform twice in a row.

In hindsight the best approach would have been to add a special virtual function in the laser transform class specifically for updating a laser transform that has already been activated. Then I could call that one every time except the first and laser transforms could opt in to handling those changes.

After figuring this all out I added the necessary code to the relevant classes that were still not handling the edge case.

The other thing I did this week, besides the usual bug fixing, also involved cases. I made a merger class. The merger class is interesting. It takes in a laser’s color and combines it into a new color. At first I considered doing this in a similar manner as Nick did with the Splitter, huge switches handling all possible combinations of color data. Instead I took some time to think about what merging really meant.

I came to this understanding: that the Primary colors, Red, Blue, and Yellow, are the most important. They act as components to all the other colors. So then I thought so what if i use their numeric values in the enumeration to calculate the composites. Like what if literally adding Red and Blue gave me Purple and adding Blue plus Yellow yielded Green. So I started checking random numbers to see if their is a good combination where the numbers added correctly without any overlapping additions. What I mean by overlapping additions is a case where yellow and blue equals green but so does red plus red. Initially I was considering any color combination that is a higher number than white to be white. However I eventually realized that there is no combination where Red < Green and Red + Green >= White but Green + Green is not >= White. So I thought how am i going to hand the case where the same color is added twice. My first instinct is just don’t do the addition. How about the cases of two Secondary colors, Purple, Green, and Orange being added together. That is when my intuition kicked in. My second instinct was that the conditions for white are that at some point all three Primaries have been added into the mix. Wait all the color combinations can be written as having Red, Blue or Yellow or not having Red, Blue or Yellow. Wait again those are 2 states. Its binary. I can write it in binary. Binary is what computers are fast at. This is great. So then I assigned Red = 1, Blue = 2, Yellow = 4, Purple = 3, Orange = 5, Green = 6, and White = 7. This allows for checking and changing colors via bitwise functions.

I finished the merger pretty quick. See you next week.