24 Apr 2016 21:40
Imagine yourself thrust into the world of 3D game design on an unfamiliar game engine. That was my experience with Danger at the Disco. Created for a week-long game jam with the Video Game Development club at UCI, I was thrust into an unknown team, and presented my first experience with Unity. It was also a bold venture into uncharted waters considering all the previous games I had worked on had been 2D using home-built engines. After the initial submission during the Winter Quarter of 2012, I worked alone on-and-off to polish the game play over the next two months. Below are some notes about various portions of development:
The project concept was conjured as a battle arena with two or more players fighting for colored tile dominion. Capture the flag style, it was touch to claim. The player with the most tiles after a set duration was deemed the victor. It was I who threw in the Disco theme. From there it wasn’t much of a mind stretch to deem the capture-able tiles the facets of a disco ball above the dance floor. With many heads turning to Super Mario Galaxy for the gravity inspiration, we weren’t sure how to pull it off. Someone eventually found a tutorial project for traversing a sphere but even with that, many hours were spent trying to code the characters so they would continually FACE tangent to the ball. That poor disco-Stu face-planted for far too long. Even then, the code was not completely understood. This led to other issues including floaty controls, and arbitrary limits to character speed. Caution to anyone lifting code from the internet; you’ll probably spend more time deciphering and debugging than intended.
In that vein, the player could gain a boost of hippie speed with a power-up and all was good. Yet, by stacking the bonus, the gravity code was unable to keep the player grounded, and they flew to oblivion! Make sure your physics engine agrees with your design choices. We chose to RESET the power-up time on collection and prevent stacking when doing power-up collection of the same type.
Our initial version only had hardcoded power-up positions, which was very lame, and unbalanced. Building random power-ups seemed very difficult at first glance. Luckily, they were accomplished post-jam by using the built-in Unity function (Random.onUnitSphere) which made the task trivial. Those Unity programming Gurus had done the hard part for us. The function grabs a random point on the surface of a spherical volume, which coincidentally, is exactly what I want for our set radius plating field.
At the time, I was absolutely flummoxed by Unity’s collision detection. The player touching the tiles actually changed their color?! Since they were all under one modeled object to my untrained eye, where was the code working? Going back today, I can tell the tiles were somehow all separated into their own GameObjects with an attached script that stored which player the tile belonged. A global method then progressed through to acquire the current team ownership count each tick. A more efficient method in the future might be to only trigger the counting code when a tile is changed color.
3D and Animation:
Considering I had never worked with 3D before, I was appreciative that we had a skilled 3D artist to model, and animate the characters. Exporting in fbx, Unity was able to read the animations from the artist’s program, and was largely painless to add. I would advise teams to ensure their pipeline is compatible with a single model first, even during a game-jam crunch before investing too much effort into their creations.
For the initial submit, the 3D animations were broken. While a certain amount of jank is dank and could be mistaken for disco groove, those fly moves were too cool for school. Two animations could “play” at the same time, with only one taking priority. The longer animation would jump the rig to its shape after the shorter one elapsed. Since the animations were directly started by a player’s button press, animations would just cut to the next one at the player’s whim. The solution for the post-jam was animation tweening. One animation would have priority over the others, which would interpolate the character’s rig to merge with it if interrupting a lower priority one. This helped for shooting or crouching which must take priority over walking at any possible stride point.
An often overlooked feature of using the animations through Unity was it allowed for selectively enabling and disabling the hitbox on the player when a certain key frame of the animation was reached. This allowed for projectile dodging on a visually pleasing frame of the animation only. This is a truly useful and underappreciated feature in Unity as it allows easy way of timing events without having to run asynchronous co-routines.
For those in the audience who have run into unexpected game lag, I have one function for you; Debug.Log. At one point in development, the code to tween colors on the disco dance floor was causing the game to LAG considerably. Why though? Debug.Log my friend. Writing anything to the Debug each frame TANKED the frame rate to the single digits.
What is a class? Hell if I knew when I started. Yet, with a little practice, the benefits became instantly clear! The player uses a class, and with some subtle tape and bandages, I was able to copy it, and assign controller function to a 2nd player in less than a couple hours. All the logic that constrains player 1, such as reacting to gravity and power-ups, applies to player 2. Local-Multiplayer! Imagine trying to write all the interactions for every object specifically for that second, or even a third player by hand? Insane!
Special shout out to one team member, who knows who they are. I would go to bed one day with a bunch of broken wanton features, and this team member would have taken them 90% to completion. He was the one that allowed finishing on time. I would suggest all beginners during a hackathon have one veteran in their ranks that can pull up the slack, and act as a mentor. Don’t have them do everything, but instead assist when they see the project flailing.
The music was shamelessly stolen from Time Splitters: Future Perfect, amongst more recognizable sources. I wasn’t pleased, but considering it was made for a Game Jam originally, and not a commercial product, it was never changed. If any of the music owners wish for me to remove the game download, I’ll do so immediately.
Finally, considering the age of the game, lack of team members, and code-breaking updates to Unity since, there is little desire to fix existing bugs. Here are some that remain:
1. The player can hit a power-up with their projectile and have it still count as collected. While an interesting mechanic from a strategic standpoint, this was not as intended. All except one power up was fixed for this bug.
2. The player can spin at infinite speed by holding their left or right key. I knew of this, yet left it because I found it funny with no tactical purpose. However, in a finished product it appears sloppy and accidental to casual observers.
3. I forgot to add an application exit command, so CTRL-ALT-DELETE is your friend…
Below you can find the download for the initial submit to the week-long game jam, and the 2-month fix-up Final release. Please take a look at both to see how extra polish can completely change the feel on a project.
Read More Biased Articles: