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.

Advertisements

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.

Jorge Castaneda: Alarming Developments

This week my focus was finishing the creation of a better lose condition. I aimed for it to be in basically its final form. Last week I started by making a general Time Display Class. All it does is take in a float in seconds and turns it into a digits that are then displayed. Next I created a light handler that can make the two cylinders strobe on and off like an alarm and then when the alarm escalates starts alternating between them. The last of the basic reusable pieces is an audio looping class that repeats any sound effect as often as you tell it to. With those three pieces I created an alarm class to tell them what to do during different times. However to be more efficient I created an alarm handler class that updates the times and keeps the alarms synchronized. The end result is this:

Alarm_smal.PNG

This is the alarm during the initial countdown. It strobes the lights ever 2.5 seconds and plays a sound effect that warns of an imminent system shut down. The clock continuously counts down 1 second at a time.

alarm_large.PNG

After reaching the ten second mark the time increases in size and accuracy, now counting down the centi-seconds. It also begins alternating the lights. The Sound effect ramps up into a resounding “System Failure” echoing across the room until the time runs out and the puzzle resets.

I also had to squash some bugs but they were small enough to not be worth talking about. Oh and I added a body collider to the player so that they can interrupt the laser to start the countdown. That was kind of important. Type again later. Bye

Jorge Castaneda: Magical Bugs and how to squash them.

Jorge here with another update about Data Thief. This week has been dedicated mostly to bug squashing, sound improvement, art asset form filling, audio student recruitment and a very serious loss… condition improvement.

As for bugs I solved an issue involving the direction and location of lasers when they go through a checkpoint. Previously the laser would only send one activation signal to the targets they hit. This meant that if you moved a laser in and around the inside of a checkpoint the checkpoint would not continuously create lasers on the other side. That is a good thing. However it also caused an unfortunate side effect. You see the way we create the illusion of one continuous stream of laser is that another laser is created that heads with the same directionality of the first laser upon activation. However since the activation is called only once the initial exit point and direction of the laser are maintained even if the original laser is being moved around. That is why to fix the bug i put the preventative measures inside the activation code instead of stop activate from being called all the time.
There was also a visual bug in the same code.  Instead of placing the new laser at the point the checkpoint collided with the laser, the code was placing it at the center of the checkpoint. This made the second laser not look like a perfect continuation but instead another parallel laser.
Last of the bugs was an issue with the doors animator. The way the door opened and closed in the code was two triggers, one trigger to unlock the door and another to close it. Since triggers only become inactive when the cause a shift in animation both triggers could be set at the same time and undo each other causing the door to permanently unlock. This was fixed by simply replacing both triggers with a single boolean so that unlocking or locking can occur one at a time.

The majority of one of the days this week was spent adjusting a poorly chosen sound effect. This was much harder than i first thought. After all not only was the bad effect an issue but its constant over playing. Fixing this required me to find a way to cancel one when the other is playing. However while I was looking for a better sound effect, and upon some suggestion I decided to find a sound that rose in tone and then end in a confirmative beep as well as its opposite a sound effect that drop in tone in the same manner. The buildup then made me think I need to edit the code further so that all the other positive feed back would be synchronised with the beep. This required playing around with Unity’s Invoke functionality for a bit. Once I worked out the consistency issues by giving the beep a little bit of leeway it sounded great. Also in case you are curious how I found the sound I was looking for. I made it myself. My teammate Nick pointed me to a handy program called BFXR. Once I quickly tested what each aspect of a sound that the program let me edit, I was able to build the sounds I needed.

Some less interesting work I did this week was continue building our art asset list although only slightly. I also gave a presentation to some bright and blossoming audio students about our game and what we need them to make for us. I told them about the core mechanics and how they relate to sound. Like how as a puzzle game the songs need to be longer and less repetitive. Or how the music needs to be built vertically with three variants we can switch between when the color perception of the player is switched. It should be interesting to see what they come up with. I’m excited for them to contact us.

Lastly is something I am still working on but I hope to have done tomorrow. I am currently making losing a little bit more exciting as well as creating some fairly reusable code. Not sure when we might need to use a clock other then under the threat of a system shut down. But I think I’ll leave the visuals of such a situation for the next update.

Jorge Castaneda: End of Month One

This month was fairly productive for me. We as a group finished making level one. We had a rocky start though. My original broke down once we realize that we couldn’t justify VR for the type of procedural puzzles I was pushing for. It was hard throwing the my baby out but necessary. It still exists and we might include it as a C feature later on. Once we dedicated ourselves to a heist game with laser puzzles the ball really starting rolling.

The first thing I worked on was a graph that maps our games base architecture, classes and the like. I learned that when you make a mind map like that you need a lot of specificity and foresight but also a bit of flexibility in how the actual code can be written. A lot of the time I went too specific with the how instead of the what. Next time I update it i will now make a checklist each function needs to hit but not explanations on how to hit those points. Also while i was modeling I was thinking in c++ architecture instead of Unity. I was not truly thinking about the built in functions of unity and what they handle. If i did some of the code we wrote would be less redundant. Also so that I get more done I should not pre-write helper functions. Instead I should focus on what each object needs and its public functionality. It still worked out alright though. It was a solid enough starting point that we got a quicker start once we started coding.

Once we began coding we got all the base classes we needed immediately out of the way. Then I spent my time debugging all the edge cases i did not account for. A useful thing that I learned about is Unity Editor scripts. Basically since our game is VR and motion controller based  and only one of us can test at a time with our HTC Vive I found a work around for testing scripts and functions. Unity Editor scripts allow you to add buttons and sliders to components in the Unity inspector. This is very useful for inputting values and testing there outcomes when put through a function. An unfortunate side effect that I did not notice until too late is that these scripts will prevent making a build. I keep them all on one file so commenting them out is not too difficult.

The majority of my work was getting the laser and the redirector to work. The redirector when hit by a laser fires the laser in a new direction set by the player. I also helped get the win condition to work properly. I was surprised by the number of edge cases I had to fix for. This requires the laser to go through all the checkpoint and goals in the room. Once these all are hit a door opens and you can reach the end of the room. This was fairly simple to do but once I started to test it is when I found out about those edge cases the redirector and laser were not handling. One case of note  was when I fired a second laser at a redirector from a second redirector the first was pointed at. The game did not like that.

After a poor third milestone after an unproductive vacation and some bizarre bugs that made the work we had done look less than it was we completed the first level. Now we had a calm amount of time to polish the level visually, audio-wise, and through haptics. While the rest of the group worked on texturing and resizing, I worked on audio effects. There is still juice needed in the coming month but I am very happy with what we got done in this cluttered month (We had a seperate class taking up our time and a vacation in the middle that threw us out of rhythm).