Sunday, December 29, 2013

Tuesday, November 5, 2013

Senior Capstone: Pixel Art and UDK

Updated 20 Nov, 2013
Updated 7 Jan, 2014
Updated 26 Jan, 2014

Some people consider Minecraft to be an ugly game.  I, however, am fascinated by the way it combines a 3D world with 2D pixel art.  In fact, I love that combination so much that I decided to try to implement it in my capstone project!  This has been a bigger pain in the neck than I could have possibly imagined before I started, so I would like to share some of what I have learned so far.  Please note that I am still developing this process, so your results may vary.  I will be sure to update this post as I glean new information, and mark said updates as best I can for anyone who might wish to revisit this post.

This guide covers implementing pixel art textures on low-poly, blocky models that have been made in Maya 2013, textured using Photoshop CS6, and imported into UDK.  I have not tried this process in other programs, so I cannot say for sure it is universally applicable.  If anyone is willing to give it a shot in traditional indie tools like Unity or Blender, please share your results!

An example of my current results can be seen below.  I also have an imgur album going which I will update periodically, for those who might be interested.

WIP screenshot from 4 November 2013

Part One: figure out your scaling

Scaling has probably been the biggest source of confusion for me.  Without approaching it carefully and methodically, you will end up with a mess of textures that don't appear to have the same sized pixels or are inexplicably blurry.  Trust me, I know from experience!

To get started, it's important to understand (or in some cases, establish) the relationship between the units used by your various programs.  Luckily, units in Maya and units in UDK scale one-to-one, so there is no real guesswork there.  Using these two programs together means you simply have to choose the size of one "pixel" in relation to this scale.  To keep things simple, I just went with a 1:1:1 ratio, meaning one pixel equals one Maya unit equals one UDK unit.  Easy enough, right?

Keep in mind that the default UDK player is 96 units tall as you begin designing and then blocking out your environment.  Make everything a power of 2-- or even better, divisible by a certain power of 2, like 16-- to ensure your models and textures will all be uniform.  Below is an example of the scaling of the player and a couple key meshes.  Precise diagrams will potentially save you a lot of time, but making a couple rough meshes and textures to see how things fit together is a good place to start if you're not sure what you want yet-- things look ridiculously huge in my diagram, but actually look and feel comfortable when implemented.

This is why I stick to pixel art, by the way


Part Two: modeling within your scale

Once you have a decent understanding of what size to make an object, you're almost ready to model.  Remember how earlier I said it'd be good to pick a specific power of 2 number to use for division?  This is where you'll first use that number-- I'll call it the scaling number for reference.  The best scaling number is one that makes it very easy to accurately model your object when snap-to-grid is turned on, but can also be used to the same effect with as many of your models as possible.  I highly recommend choosing such a number and just designing all of your models around it-- 16 has been working well for me, but your needs may differ.  Divide your width, height, and depth by this scaling number and write those results down.  If any of them aren't a whole number, you either need to adjust your design to fix it or choose a new scaling number.  Fractions kind of defeat the purpose of using snap-to-grid, after all-- you can get away with the occasional half, but whole numbers will make things less painful.

Use your calculated width, height, and depth to model the object.  Stick to the grid with every change you make.  Inserting and edge loop?  Align it to the grid.  Extruding something?  Align it to the grid.  Mending meshes together?  Align that seam to the grid.  It can be tedious at first if you're used to the freedom of organic modeling, but the blockier the model, the easier unwrapping and texturing will be.  That being said, you don't need to be overzealous with dividing your surfaces into grid units.  If your 4-units-wide object doesn't need inner edge loops, take them out.

Below is an example of one of my objects, a torch.  In-game it is only 32 units tall, so I used a scaling number of 4 to allow me to actually add some detail to the model.  Note that each piece aligns with a whole number of units in the grid-- the top piece is 2 tall, the middle 2 tall, and the bottom 4 tall.

Note that the top does need to be completely divided, but the side doesn't need as many
horizontally-running edges, thus they were omitted.

When you're done modeling, don't forget that you need to move your pivot and rescale your model.  For the pivot, I recommend placing it in a spot that will make it easy to place the object within UDK.  The pivot on this torch is kind of arbitrary considering the way I'm using it.  For my pillars, however, I placed the pivot at the bottom corner of one side, placed in such a way as to ensure snapping it to the grid in UDK will make the bottom meet my floor.  After you place the pivot, snap the entire object to the very center of your grid.  Then scale it on all axes by your scaling number so that it will become the size you want it to be in UDK.  I've been exporting my models as FBX files-- if you do, too, make sure that "smoothing groups" is checked in the export options.

Finally, import the model into the UDK editor.  If you need to make changes, updating the model is as simple as re-exporting it, right-clicking on the mesh in the Content Browser of UDK, and selecting "re-import."  We will most likely be using this extensively in the texturing phase.


Part Three: how the hell do I texture this thing?

This is the part of my overview where I still do things wrong from time to time, so please bear with me as I revise the section for clarity.

Remember that magical scaling number I keep carrying on about?  This section will make it clear as to why you might want it to be consistent for every model you make.  However, it may also confuse you as to what this number actually means, as it seems that our assumption that 1 UDK unit equals 1 Maya unit equals 1 pixel was not quite accurate.  I'll try to explain as best I can despite not fully understanding it myself.

Using our assumption of a 1:1:1 unit ratio, our scaling number becomes the number of pixels wide and high each unit square in Maya is equal to.  Below is an example using a pillar.  The background is a grid of 8 x 8 pixel squares in a 256 x 256 image.  In-game, this pillar is approximately 64 x 64 x 256 units.  I used a scaling number of 16 when modeling it, so I modeled it as a 4 x 4 x 16 and then scaled it up when exporting it for UDK.

Using the entirety of your UV space doesn't really work when you want things
a uniform size.  That's my story and I'm sticking to it.

If everything is 1:1:1, shouldn't one square on the grid be 16 x 16 pixels-- in this case, a 2 square x 2 square chunk of our grid image-- considering our scaling number was 16?  I thought so too.  Unfortunately, BSP seems to use a different scale, where each unit is only 8 x 8 pixels when compared to my 16 x 16.  In other words, pixels seem to appear twice as big on BSP as they do on your meshes.  If you're not using BSP, this is pretty much irrelevant and you can continue along your merry way without worry.  If, like me, you are using it, you just need to decide which way looks better to you.

To continue my explanation, I'll choose the scaling number 16 to be the correct representation of how many pixels high and wide a Maya unit square should be.  Open up Photoshop and make a grid image like the one shown, except using 16 x 16 pixel blocks.  Use this to scale your UVs so that each Maya unit square aligns properly with a square in said grid image.  Below is an example using a sconce.  In UDK, it is 64 x 48 x 64; using my scaling number of 16, it became 4 x 3 x 4 as I modeled it in Maya.  Each square in the grid image should be 16 x 16-- here it's 8 because I was doing it wrong and didn't realize it until I had figured out the inconsistency I discussed in the previous paragraph, so just pretend it's 16.  I modeled it as a series of Maya unit cubes since the design was simple.  Since our scaling number says each of those units should be 16 x 16, we needed to scale the UV map so that each unit matched the squares in the image grid, like so.

These UVs will be twice the size when I revisit this mesh, as I was scaling incorrectly-- the image grid
uses 8 x 8 when it should be 16 x 16.

If you run into a situation where your scaling number is different for a certain mesh, you'll need to keep this in mind while adjusting its UVs.  For example, the torch had a scaling number of 4, so each of its Maya units are 4 x 4 pixels.  Compared to the sconce above, where a Maya unit is 16 x 16 pixels, the units are 1/16 the size.

The sconce is on the left, and the torch on the right.  The torch UV is a fraction of the size of the
sconce UV, but the pixels in the end result appear the same size.

You may have noticed that I'm overlapping a lot of UVs here.  With some of my meshes, this will be necessary to ensure everything can be scaled properly.  With others, it's to save me time when I actually make the texture.  This is one of those decisions that depends on what suits your needs best.

When scaling and aligning to the grid image, be careful of the edges.  They should fall as precisely between each square as possible, or else you risk having the edges bleed a little because they'll be encroaching on additional pixels.  This is where UDK's ability to re-import a mesh with a couple clicks becomes very useful.  If your texture doesn't look quite right in your UDK preview because a UV is slightly askew, you can fix it, export the changed file to save over the old one, and then re-import it pretty quickly.  I did this a dozen times while working on my torch texture, as its parts were too small for my grid image to be useful and I kept misplacing the UVs.

Updated 20 Nov, 2013  I have discovered a way to make aligning the UVs a lot more precise.  Thanks to this tutorial on lightmaps from World of Level Design, I was able to set my UV editor grid to actually do something useful and represent pixels.  This information is at the bottom of their tutorial.  Once you have a pixel-sized grid set up, you simply need to snap all your UV edges to said grid.  If you used square/blocky models like I did, this will be super easy-- you can resize everything just by snapping instead of trying to uniformly scale all the UVs in one go.  Nifty, eh?  I'm still getting the occasional edge bleeding, but I suspect this is inevitable with UVs.

Updated 26 Jan, 2014  So it turns out that while snapping the UVs to the grid gets you most of the way there, snapping to pixels is actually an option in the UV editor and it seems to take you the rest of the way.  Once you've sized everything properly using the above technique, come back through for one more pass, this time with "snap to grid" turned off and "pixel snap" on, like so:

Note that "pixel snap" is inside the UV editor window

Once you have the UVs aligned so that they won't chop any pixels in half, you can save them out for use in Photoshop.  If you haven't already, don't forget to export the updated model and re-import it in UDK, or the UV mapping won't be there.  Here it is also important to pick a resolution that won't require stretching.  For example, I have one large mesh that is nearly 512 x 512 units.  Using a texture on it with a resolution of 256 resulted in blurry pixels because of the way the texture had to be stretched across the mesh.  However, the rest of my meshes so far have been fine with textures of a 256 resolution, as they are all 256 units or smaller along their 3 axes or have UVs that can be arranged to fit a 256 comfortably.

Hopefully I don't have to tell you how to use Photoshop.  Just give it a lovely pixel texture and save it out.  I am still not sure what the best file type to use is.  Some textures have looked fine using .TGA at 32 bits/pixel, but others suffered from noticeable artifacting that only went away when saved as a .PNG with no compression.

Getting the texture into UDK is just as easy as with any other.  There is one setting you need to change on each one, however.  Double-click on the texture in your Content Browser to pull up its info menu.  The option labeled "filter" needs to be set to "nearest" to prevent it from making your pixels all blurry.

The only setting I have messed with so far.

With a little luck-- and if you're clumsy like me, a lot of cursing-- you should now be able to add the texture to your model using a material and then step back and admire your handiwork!


A quick note on particles

I find particles to be a lot of fun, so I can't imagine skipping them in this overview.  Pixel art particles don't take much more than regular particles, really-- just remember to set the filter to nearest on the texture and you're good to go.  I personally have been using .PNG files ranging from 1 pixel to 8 x 8 pixels, adjusting the size as needed within the particle effect's options menu to make it look pretty.  If you haven't made a particle effect before or need a refresher, this really brief video series covered everything I needed to get a fire particle up and running.  My "flames" are just a tear-drop shaped red-orange-yellow thing and my "smoke" is just a 3 shades of grey block.

Simple yet effective, I'd say.

Wow, this was a long-winded post.  Congratulations for those of you who made it through.  I hope this helps someone out there get some awesome-looking pixel art into their UDK project.  If you have questions or comments, please let me know!

Updated 7 Jan, 2014  Rendering these models in Maya

If you've tried to render any of these models in Maya, you may have noticed that they are horribly blurry no matter what rendering settings you try-- in vain-- to change.  This is because Maya is dumb and just assumes you want an ugly filter on any images you use in your shaders.  To remedy this, click on the shader you're using as your texture and follow its color node until you find the file settings.  At the top of these settings, there is an option called "filter type."  Set that bastard to "off" and you should suddenly have nice, crisp renders!  To get the same effect in your viewport, hit the "shading" menu in the viewport's options, click on the little box next to "hardware texturing," and set the filter there to "unfiltered."  Better?  Good!  (I now have a blog post dedicated to this problem-- click here to see some diagrams showing where these settings are!)



Sunday, November 3, 2013

Senior Capstone: Project Introduction

Hello again, internet!  It's been quite some time since my last post, but this time I was actually doing something useful between then and now.  That "something useful" is the focus of this post!

This is the final semester of my undergraduate career, thus the semester in which I'm to complete a senior "capstone" project that shows off all the fancy things I've learned in the past four-and-a-half years.  As I hope to eventually become a video game programmer, I wanted my project to focus on programming for a small game.  Believe it or not, the majority of my hands-on school-induced programming experience has been in the Unreal Development Kit, so I approached the professor who had taught me how to use it and asked him to be my advisor.

Our discussions led me to decide that the project should be a short level for an adventure game.  I had those old Flash-based point 'n' click games in mind when I started, but the idea morphed to include a more modern 3D experience, using a first-person camera and allowing for free movement throughout the entire space.  Navigating through the level consists of picking up and using items to solve puzzles.  At this point, these puzzles range in difficulty from putting an object in a certain place to comprehending a logic-based riddle.

My initial level design had a vague, needlessly open layout, but the puzzles I came up with gave me a good start for my revisions.  I haven't actually taken my school's official level design course, so the design I landed on isn't exactly a work of art.  However, my advisor said it would suit my purposes well enough, and I didn't want to argue-- after all, I was more interested in getting the Kismet together than anything else when I started.  Below is the sketch of my general level layout.  For those of you who aren't experts at deciphering scribbles, the map consists of three different ground heights, a few buildings, a few underground passages, staircases in varying states of disrepair, and a player path that sort of resembles an ampersand.  At least, the sloppy way I draw them.  The overall goal is to light the four magical beacons so you can enter the chamber of... erm, something.  I haven't quite figured out the details of the story yet.

This is still pretty accurate, actually...

The level is inside a spacious graveyard, but I'm not currently aiming for a horror game.  This combined with my lack of organic modeling skills encouraged me to decide on a low-poly, low-resolution art style.  As I spent a considerable amount of my summer working on pixel art, it seems like a nice representation of my skills.  If I ever revisit this project after its completion, I may change this approach; for now, it suits my needs well enough.

So far, the most fun I've had was while putting together the Kismet for the level.  Most of my design required relatively simple programming-- things like picking up items and opening doors-- but a puzzle that has you lighting torches in a specific order required some head-scratching and a couple re-implementations.  At this point I am calling on a few Flash files to add some fancy text to a puzzle, but am largely depending on the pre-built announcements of the UTDeathmatch game style.  I hope to replace this with my own solution before the end, even if it's just to replace the HUD with a player inventory display.

I have a small imgur album set up for this project, which I hope to fill as I get more assets finished and presentable.  Of course, I will be updating this blog with more information as I find the time.  My goal is to cover the major parts of this project in detail so that people other than me can benefit from the weird bits of things I have learned and will be learning while I complete this project.

Until next time!

Sunday, June 16, 2013

Simple Turret Using UDK and Kismet

/* Long-winded introduction */

Hello, internet!  As I probably haven't mentioned, last semester I was in a course called Virtual Environments at my university.  For our final project, I ended up in a group with a guy who was very eager to make more than just an environment-- he had an idea for an interesting yet simple game level.  Since I like to pretend I'm a programmer, I immediately said I'd love to try some Kismet and see how game-like we could make the level in the few weeks we had to do the assignment.

The "level" we turned in was definitely impressive, considering it came from a beginner-level class that had just barely skimmed over some of the basics of Kismet.  I only feel comfortable saying that because the rest of the class said it was awesome when we presented it, by the way!  However, it was missing one of the most interesting gameplay aspects-- turrets.

Yesterday I started work to add them.  This is what I have so far.

Please note: this is a work-in-progress.  You are welcome to use this code as you see fit as long as you're aware that parts may not work right all the time or at all on your build.  I'm new to this, so I may not be able to answer all of your questions about this code or the inner workings of Kismet/UDK.

Note: the game type used in our level was UTDeathMatch.  I'm not sure if it's a necessary setting to make this stuff work, so I figure it's best to let you know just in case.

/* Turret details */


Our level's turrets were imagined to be rather simple-- player gets in front of turret, player gets shot; player shoots turret, turret falls over and stops working.  The best comparison I can think of is the turrets from Portal.  To accomplish this, I needed to main functions:

  1. Shoot at player
  2. Respond to getting shot by player
/* Kismet details */


Our first function is circled in red and labeled #1.  My Kismet is a complete mess, so I'll summarize.  The code begins when the player Touches the Trigger Volume I have placed in front of the turret.  Note: don't forget to set the Touch node's "max trigger count" to 0 like I always do!  On touched, it sets our "if" statement to true; if untouched, false.  If true, we go to a section of vector math that gives us a location to spawn projectiles.  For this mesh in particular, I want it to be about 150 units above the pivot point, where the pivot point is currently slightly in front of the turret's gun but level with the floor.  After that, the code gets the player's location as a vector.  This is necessary because the Spawn Projectile node can't have a Pawn as an input for some reason.  Now the PlayerLocation and SpawnLocation vectors are fed into Spawn Projectile.  I have chosen the rocket from the drop-down list in the node's settings, so a rocket will be fired at wherever the player was standing when this function was called.  I included a delay at the end of Spawn Projectile to keep it from shooting too rapidly-- if the player stands in the Trigger Volume, the turret will shoot rockets at him/her every two seconds until the player either leaves the Volume or dies.

Whew!  Seems a lot less complicated in my head!  This next part gets even hairier, so take a breather if that one wore you out.

The second function is the part that's messy and may not be working right.  I seriously doubt this is the best way to handle this, so please let me know if you have a better solution.  Note: the turret is currently set as a KActor-- I don't know if this code will work with any other physics setting!  Our first step, labeled in blue as #2, is actually quite simple.  Here we just get the turret's rotation when the level first starts.  This is so we have a point of comparison in the next step.  In the section labeled in orange as #3, we are telling our turret what it should do when it gets shot.  In this case, we want it to figure out if it was rotated far enough to be considered toppled over.  I put a brief delay after the Take Damage node to give it time to fall, and then get its new rotation.  The code looks like a huge mess here because, unless I'm just doing it wrong, vector math in Kismet is unnecessarily complicated.  It's really just checking to see if the difference between the new rotation and old rotation is significant enough by subtracting the two, getting the absolute value of the result (I had to code this node myself, mind you), and then compare it to a value I determined to be "far enough" (in other words, about 45 degrees multiplied by 182.044 to get the UnrealScript rotational units).  If the rotation of the X or Z component is "far enough," then the turret's Trigger Volume is destroyed and a message pops up letting me know it worked.  Note: you might notice that the Y component is there but not being considered-- that is because shooting the turret in just the right place long enough will cause it to rotate in place but not fall over, which will incorrectly trigger the "death" of the turret.  It looks like it should be the Z component doing this when looking at the turret in the editor, though, so I think it's a byproduct of creating the mesh in Maya, where Y is up.  I'm not sure about this theory, so let me know if you have an explanation!

/* Conclusion */

It always kinda surprises me when I get stuff like this working, even though it looks so simple when you're the one playing the game.  I think next I'm going to see if I can't add a dynamic trigger volume so it'll keep shooting you if you rotate it in place, and then a blinking light or something to make it more obvious which turrets are on and which are off.  I'm starting to think just diving into UnrealScript and making a new class for this would be the best way to finish it off, but I'm not sure how to translate some of the Kismet functions just yet.  I'll be sure to post an update if I do, as it'd be a lot easier to test out a new class than try to reproduce my Kismet!

Thanks for checking out my work.  If you have any questions or suggestions for improvement, please let me know.