Tuesday, July 23, 2019

Kaiju Kaboom!

I am pleased to announce the release of Kaiju Kaboom, my first commercial game project. You can find it on Google Play, exclusively playable on Daydream.

Most summers, I set my own work and creative goals rather than teach classes or work on grant-funded projects. During the Spring semester, I decided that one of my summer goals would be to create a game from scratch and release it commercially. The outcomes of this plan are objectively measurable, and as of last night, I have met them, and I feel good about it.

The game

The game itself is an expansion of the concept that my son and I developed for Global Game Jam. Inspired in part by Terror in Meeple City, the player takes on the role of a kaiju who returns to its island home, only to find it infested with people. Of course, the people are meeples, the buildings are made from wooden blocks, and you are a miniature giant monster, but this both adds to the charm and simplifies the asset development for a novice modeler. The biggest change to the game is moving it to mobile VR via Google Daydream, but I also added randomized levels, meeples that fight back, and four different kaiju powers, three of which are unlocked through the high score system.

I spent some time around finals week building a proof of concept to ensure that the game would be enjoyable and within scope, and having a positive experience with that, I devoted the summer to it. I did not use any formal task tracking tools. Instead, I have a pad of paper on my desk where I would either write down features to explore, sketch geometric or software solutions, or record defects to address. I worked roughly eight to ten hours each day, sometimes up to twelve, and about half days on Saturday, with a few gaps for family trips. I showed an early build to some friends and family around Memorial Day, and this confirmed to me that the core gameplay was really enjoyable.

The tech

Kaiju Kaboom was built using Unreal Engine 4. I started the project in Blueprint and initially just added C++ for the parts that were faster to write in textual code than they were to prototype in Blueprint. In retrospect, there are parts of the core game loop that I left in Blueprint which I probably should have done in C++, because the Blueprint can get hard to follow. I don't think there's any real performance hit from using Blueprint here; the real problem is that Blueprint makes it harder to control modularity, so it's hard to intuit the dependencies after walking away from a subsystem for a while.

Getting up and running on Daydream was not much trouble, and the documentation is good. However, the Google VR branch of UE4 is clearly no longer being maintained. This led to a problem as I was getting ready to release, in which the game crashed on a friend's device. Scouring the web, reading semi-related threads, and trying various approaches, I was able to finagle a build system that worked for both of us. I continued to do my regular feature development in UE4.22.3. For releases, however, I downloaded and built UE4.22 from source, replacing its GoogleVR libraries with those from 4.20 release—the most recent release—of the googlevr-unreal fork. My friend also had some troubles that I thought might be due to texture formats, so the build includes both ASTC and ETC2 formats, even though only the former is needed for my own Pixel 2.

The null business plan

At this point, the thoughtful reader may ask, "Why did you target Google Daydream?" The simple answer is that I have one and it seemed like fun, both as a technical challenge and through that proof-of-concept I built in early May. Note that mine was a commercial project not because I wanted to make money but because I wanted to see what was involved in making it a commercial project. I know literally one other person who has a Google Daydream setup: my friend Chris, who was my lone tester. If I can sell ten copies, I'll buy some nice beer. I'm in the blessed and enviable position where I can invest a summer in learning and improving my skills without it having to be economically profitable. As I alluded to before, abother benefit of Daydream is that because it's low-powered for VR, I could get away with my own limited asset-creation skills, whereas I know I could not make something by myself in two months that would be competitive for, say, the Vive.

I did borrow an Oculus Go from a friend, in hopes that it would be easy to release on both platforms. Unfortunately, the logic of my character was tightly coupled with the GoogleVR components, and I didn't see a clean way to separate these. I would consider buying one of these $200 headsets and doing a port if I had any belief that my little hobby project could make at least that much back plus porting time, but right now, I don't think I can put that much more effort into it, since I need to transition into "preparing for Fall semester" mode.

The last two or three days, as I've geared up for the public release, I have thought that perhaps I should have planned on doing a more modern release, where the first part of the game is free, and people who like it can pay to unlock the rest. One reason for doing this is so that I could explore both the libraries and the platform support for DLC and licensing, which would be interesting. I decided to stick with my original plan, augmenting it slightly by releasing the game under the GPL. This means that if someone buys the game, they get access to the source code as well, and they are free to learn from it just as I did. I don't know if that will have any real impact, but it feels like the right thing to do, given my situation.

The learning

Originally, I had it in my head that I would try to make all the assets of the game from scratch in true artisan fashion. Along the way, I did use a few public domain sound effects, and as my available time quickly ran out, I added CC-BY music from indie- and jam-favorite Kevin MacLeod. I have written two other posts to detail some specifics about things I've learned through this project: importing Blender animations into UE4 and using UE4 LiveCoding for rapid unit testing. I did not keep a rigorous log of other things I've learned, and some things I had to learn twice because they did not stick in my head. Here, however, I am going to try a brain dump, in part so that I can come back here later when I need to re-learn something again.

Blender

  • UV Unwrapping
    • I found this video in particular to explain well how to unwrap and texture paint, which technique I used to mark out regions of a texture for manual painting in Gimp.
  • Normal maps
    • The technique involves modeling high-poly and low-poly models in the same file, exporting the low-poly one (by selecting it and exporting only the selection) for UE4, but exporting the normal map of the high poly one and using it. I used this on an early version of the blimp.
  • Smooth shading instead of normal maps
    • An easier way to do what I wanted with normal maps was to simply select Smooth Shading from the Tools menu in Blender, and to make sure this was exported to FBX.
  • Boolean modifiers
    • These modifiers enable constructive solid geometry; for example, the union of a plane and a sphere was used to generate the blimp's fins
  • Keyframes in video editing
    • Just as explained in this video, I had been doing gamma cross fade effects, but now can do more robust effects by keyframing. Right-click on a property, insert keyframe. I'm still not sure how to see all the keyframes and move them around, but this was good enough for me to compose the scaling and fading effects of the trailer.

Gimp

  • Filters→Render contains all kinds of neat stuff to play with visual effects. I used the Lava and Cell Noise filters to generate quick but effective textures for the fireball and acid spit spheres.
  • Multiple monochrome images can be packed into the RGBA channels of a single image using the Colors→Components→Compose feature. Make each image into a separate layer, and then this tool allows you to directly compose the layers into the RGBA channels.
  • Two ways to add shadows behind text:
    • A "soft" shadow can be had by copying a text layer, darkening it, and then blurring it. I did this at some point in the past, though I cannot remember where.
    • A harder shadow is possible by using Filters→LightAndShadow→DropShadow.

UE4

  • AI vs Physics
    • An actor cannot be driven both by a behavior tree and by physics simulation. Of course not, he says in retrospect, that would make no sense.
    • There are actually two meeple actor types in the game: AIMeeple and PhysicsMeeple. AIMeeple is controlled by one of two behavior trees, depending on whether they are armed or not. When they are hit, they convert in-place to a PhysicsMeeple.
  • AnimGraph
    • I had done a little with AnimGraphs for an unreleased tech demo last Fall, but very little of that stuck in my head, in part because I may very well have been doing things wrong. For Kaiju Kaboom, AnimGraphs are used in a more conventional way, driving the animation states of both AI and Physics meeples.
  • Landscape Materials
    • The landscape has sand and grass layers, and it fades toward white with higher altitude.
  • Cascade Particles
    • I was hoping to learn Niagara, but it is not supported on Daydream. Still, I was able to learn enough of Cascade to make my own simple particle effects, such as the fireball explosions and acid spit splash.
  • Following a Spline
    • It's a fundamental technique in level building, but I haven't really done much level building before. The blimp's flight path is specified by a closed spline.
  • Efficient Materials
    • I learned some more about how to balance GPU and CPU processing. For example, my original implementation of the blimp's propellers involved using a rotating movement component for each. After watching some videos (possibly one of Tharle VFX's shader maths videos), I moved this to be computed by a shader using world position offsets.
    • Several of my materials use customized UVs so that they are computed per vertex instead of per pixel.
    • I have a few "master materials" and use a lot of material instance constants. I understand this to be more efficient, although I didn't go so far as to measure the difference.
  • Visualizing Shader Complexity
    • As mentioned above, I haven't really done a lot of level design in UE4, so I've never really needed to inspect my scenes for performance problems. On this project, I tinkered some with the different editor view modes such as shader complexity, in order to find areas that were not performing how I expected. Turns out, everything was performing as I expected, but it was still neat to see this.
  • Unit tests
    • I knew it was possible to write unit tests for C++ code in UE4, but I had never done it before. TDD seemed like the best way to approach my high score table: unlike experimental gameplay code, it had very well-defined rules. Here is the source code for the unit test. The testing library assumes all the tests are in one method, and so I have used macros to give a fluent layer on top of that assumption. This is not as robust as something like chai, but it's much easier to read than the alternative.
    • I did not have a continuous integration system, so I had to run the tests by hand, which means that I rarely ran them. If I were working on a team on a larger-scale project, I would definitely invest in CI.
  • Functional tests
    • As with unit tests, I have known for some time that it was possible to do automated testing through the UE4 session frontend, but I never took the time to really figure it out. In this project, I created a test level containing four automation tests in a 2x2 format to ensure that falling columns and floors damage AI meeples and physics meeples.
    • In my original approach, I was spawning the relevant actors in the PrepareTest event of the Blueprint. Later I realized that it was much more effective for me to create these actors as child actors within the construction script, since this allowed me to see and manipulate them in the level. 
    • The result is fun to watch, but the approach was somewhat hamstrung by the fact that I was not using continuous integration as mentioned above..

Wrapping Up

It seems like there's no end of good ideas that I did not have time to put into the game, ranging from minor quality-of-life improvements to major new features. The spirit of this project is inspired by Jeff Vogel from Spiderweb Software, who taught me this wonderful expression: It's better than good—it's good enough! I'm pleased to have this project more-or-less wrapped up for the summer. I have started doing some course prep, but I have more of that and other university-related business to take care of this summer, as well as family obligations. 

I've also done much of this work with an injured middle finger on my right hand, which, combined with the intensity of this project, has left me well behind on my summer painting goals. Now that Kaiju Kaboom is out in the wild, it may be time to clean up the office and get the paints out.

Thanks for reading! If you know of someone with a Daydream who you think might enjoy throwing boulders at meeples, please let them know about the game. That is, pretty much, my marketing plan.

No comments:

Post a Comment