Sunday, October 30, 2016

Maya LT - Good Value or Dead End?

C'mon in and play, what could possibly go wrong?
C'mon in and play, what could possibly go wrong?
Earlier this year I took a risk and bought Maya LT, a 3d authoring tool that Autodesk claims is perfectly suited towards indie game developers, especially if you use their game engine (StingRay).

After six months of constant use in production of our next Unity game, we've come to the conclusion that the LT version was a mistake for us. But first-

The LOVE part... It's fast

After years of using & teaching Max & Maya, Maya LT is a breath of fresh air for the core modeling & animation tasks needed in our game.

1) It's nice and fast. Starts fast, runs fast, and is fairly stable (occasional freeze-ups). You can run multiple instances without really taxing your system.

2) Easily design PBS materials, or use & edit Substances which has been great.

3) It's priced smartly to make it accessible to your average indie developer. A 1-year license can be had for $240 US, or monthly for $30.

Using Maya LT, I built custom rig controls for my Mixamo characters, and happily animated away for months. But then some hard realities became apparent.

The HATE part... LT is where your data goes to die

1) It's a tomb - Scenes you create in LT cannot be loaded into full Maya. You are limited to FBX, so forget about migrating your IK rigs or anything else that uses maya-specific data.

This is a significant misstep on Autodesk's part. We're investing heavily to create assets for our game, but fully expect to re-use them again in other games. This means we're locked into LT permanently, or have to make the hard break and rebuild it all again in full Maya if we decide to upgrade.

2) Not Full MEL - Check out the product comparison list that compares LT to Full Maya. See those check marks next to MEL scripting? That would lead you to believe that LT includes full MEL, but in fact it's gimped. For example, MEL in LT does not allow "Fopen", "Fwrite", "FPrint", etc.. In fact they've closed off any way to share or move data outside of LT, including removing the AnimImportExport plugin.

3) Can't integrate with Source Control or External Export Scripts - Yes, the lack of .NET API support is shown on the comparison list. But what serious Indie Developer doesn't use source control? And you cannot run shell commands from the OS. So interfacing with TFS becomes a non-starter, gotta do it old school (wasting time & introducing human error).

There are other annoyances that are typical for a 3d Package. But the above 3 items alone have me seriously considering buying a full Maya license and re-building our assets there so we're not trapped in a diabolically closed, walled garden that would impress Apple engineers.

I understand all the security arguments and why Autodesk built all this firewall code. But honestly, developers write plugins and extend the tools to solve problems in production. Maya LT is a good short-term solution for limited content creation, but falls well short in it's goal of improving indie development.

Saturday, August 20, 2016

Your Curve Editor is a Damn Liar!

Professor Bunsen explains Maya's curve editor to Beaker
Professor Bunsen explains Maya's curve editor to Beaker

This is one of those blog posts I'm writing in the hope that I've foolishly overlooked something obvious. Where some smart person would reply with "Hey n00b just click these 3 checkboxes and bada-bing you're all good".

Where do I start? I'm not an animator, but I need to be one for our current game project. I'm animating characters for a first-person action game we're building in Unity 5.

While a lot of the motion is specific, in many cases the player controller input drives movement, like looking around, and turning the character, etc.. So these actions need to use very high precision linear animations for a lot of different reasons.

In pursuit of trying to get all that movement correct we ran into tangent & curve issues in Maya that caused a fair amount of pain. 

If you animate a character in Max or Maya, you probably use IK and a control rig on some (or all) of the skeleton. When it comes time to export clips to Unity, normally you would bake everything down to the joints, either inside Maya, or upon exporting an FBX file.

And that's where the fun begins.

The first sign of problems cropped up when I needed to do a very short, precise animation that switched between two poses. The animation was three frames, where the first frame is a reference pose, and the next 2 frames are the target pose. 

My first inclination was to set frames 2-3 to Linear Tangents, both in & outgoing. In Maya's curve editor it looked right. But once we had it in Unity it was doing really weird stuff. 


To check, we imported the FBX into 3ds Max and saw a big difference. Here is the same FBX file side-by-side in both curve editors:

When Linear is not Linear
Seriously, who is responsible for this?

Really? Yes, this is specifically a problem with how linear tangents are handled (and displayed) after the baking process in Maya. 

Maya was lying. Regardless of what tangent type is selected, once baked your selected tangent type will revert to Auto.

This little gremlin would rear it's ugly head again, when a few days later I had a joint rotation that had a linear curve, but once baked, the first & last keys would reset back to auto tangents! This is what I'm talking about in a simple example:

No idea why this happens. As you may know, there's two ways to bake keys in Maya. When you have an IK control rig, it's nice to use "Bake Simulation" to bake everything down to the joints. Then you can delete all the controls and be left with nice clean joints to export.

Or, you can skip all that, and let the FBX Export bake your animation (not as elegant, you can select the joints and use Export Selected, but it may still include control rig elements). 

Now, you would think that either of those baking options would produce the same curves result, right? Wrong.

In the most aggregious case, I had a turning animation where the character's hips would rotate from 120deg left to 120deg right. We use this as one of the axis of turning for when our character looks around.

The hip joint is rotated off cardinal axes in the character's normal pose (this is a Mixamo rig). If you turn the upper body from left all the way to the right, your hip joint would rotate on world Y (up) axis instead of local. So you would naturally end up with curves on all 3 axes.

What could go wrong? Well, here are the Maya rotation curves on the hip joint from using Bake Simulation vs. just FBX Export (with bake option checked):

When a curve is not a curve
Continuity be DAMNED

Aye Carumba! How could the animation you saw above be represented by those curves? What is that, gimball lock? I have no idea what I"m looking at here.

And that's where things get serious. Is this just bad math in Maya? 

Usually this is where I step back and say "ok, there's no way this could be the software, we must be doing something wrong"... only to arrive back at the same point. So then I thought, what if I did the same animation in 3ds Max, would the curves look the same?

Answer: NO

After a re-building the control rig & setting up constraints in Max, I created the same exact animation of the hip rotation (Note: in Max, there's no way to internally Bake Simulation like in Maya, you can only export FBX to bake). 

Once again we re-import the FBX back into Max and lo & behold, look at the (vastly improved) hip joint rotation curves:

Max saves the day
Order is restored in the galaxy.

So let me make sure I have this straight:

1) Two 3d packages from the same company
2) Both cases using Euler rotation controller on Hip joint
3) 3 different curve/tangent results from the same joint in the same animation

See, this is the kind of thing that will rapidly accelerate the aging process for an old art dude like myself. 


So now, please tell me I missed something really simple. Or stupid. I would gladly take either at this point. 

(special thanks to my collegues at Digital DNA Games for the endless support and assistance in untangling this hella knot).


Tuesday, April 5, 2016

So many mouse clicks...

I really need to blog more about game development stuff, but sometimes you're so deep in the woods that it's kind of overwhelming to break it all down in a way that people could obtain something useful from it.

In the last six months my work has been dealing with Unity 5, here are just a few of things I've been focused on:

- working around the huge grenade Unity threw into lighting... just... FFS ENLIGHTEN!

- accordingly putting real-time, baked, and mixed lighting modes through endless trials in an attempt to get useable results

- creating big terrains (8km) with high density vegetation, road systems, and placed structures

- clothing swaps for characters, and building an efficient rig to support this (ongoing)

- vehicle rigs with character drivers, support for co-op players

Once we get this next game out I will probably spend a few weeks just writing up the process and challenges we've been going through.

Until then let's just say that nothing is easy, any substantial gains are a hard-fought, perpetual process of trial & error. :)

Saturday, October 17, 2015

Notice of Project & Authorship Change

This post is just to officially notify all that as of September 30 2015 my work & involvement with the game project known as Savage Lands Early Access has come to an end. The fine folks at Signal Studios are taking things forward, and I wish them the best of fortunes. It was quite an experience!

What's next? An exciting new project is kicking off and I really look forward to briefing everyone on all the cool details as soon as we're ready to show!

Cheers, -H

Friday, May 29, 2015

What is Collaborative Art Process?

Everyone on the team needs to contribute action.
A good art director in game development should be able to communicate a vision that is compelling, yet realistically attainable in a production sense.

But how the A/D goes about including the whole team in the process, from all disciplines, is the key to a healthy culture. No one should ever pretend to be an absolute authority on everything. That doesn't exist.

Knowing one's limitations, and working with people who complement them gives a project the best chance of success. It should never be about ego, instead always about making the game better.

I have a rule that I set when working on game project:

Anyone who feels something in the game could or should be better is encouraged to offer up a better solution.
But they have to show it, not tell it.

Think the lighting isn't up to par? Great, start up the game tools, build a better rig, and demonstrate why it's better. Assuming it looks better and runs efficiently, why wouldn't we want that?

Of course we would. We all want the game to be better.

In non-territorial development, we should always welcome & encourage this positive energy from competent developers.

But what if a team member's proposal isn't better?

In that situation the person putting forth the effort should be rewarded with a concise, professional explanation that is steeped in art fundamentals & best practices. Not "I didn't like it". That is in no way fair or respectful.

We learn from each other, and we grow stronger. That's the essence of collaborative art process.

But, it can all go wrong is when tell supplants show. Talk is a data point, action offers up real solutions.

Avoid becoming or collaborating with a person who believes that talking about game dev is actually creating something.

These people sometimes closely guard their role and build a fictional narrative about their worth. They may attempt to counter their lack of substance with politics or drama.

These are toxic elements which can fracture a healthy studio culture and mute collaboration.

As an art director or studio manager it's absolutely your responsibility to nip this kind of thing in the bud. Let it fester, and watch your team stop trusting you.

The people you work with are important. 

After you spend enough time in the industry you will seek out collaborative folks who know their stuff and are pleasant & professional to work with.

Nurture this culture, and evangelize it to everyone you work with. Build up a team that collaborates freely and creates the best game possible!

Tuesday, March 17, 2015

Environment in Savage Lands: Part 3 - Vegetation and Chopping Down Trees

Deer feasting on polygonal sprites in Savage Lands
screenshot from Savage Lands

In the previous post, I went through the process of applying textures to the terrain. Next I will be talking about nature content like trees, grass, & rock. Also, how content was made for the tree & bush destruction in our game.

Finding the Right Look

When I first set out to do an arctic tundra environment, I erred on the side of happy. In the first revisions of the world, I put a lot of green in to break up the snow and create an appealing look. But it wasn't harsh enough, and didn't differentiate us enough from other games.

Here's a screen from a very early prototype of the game:

early test environment
early test environment
I needed to go with a more hardcore, brutal look instead. Less Canadian Rockies, more desolate Siberia. Time was a major factor, we were hoping to get early alpha versions up & running within a month.

Almost everything we bought from the Unity asset store over the course of the project turned out to be disappointing, whether it was tech or art content. What often looks good in the store window turns out to be less than promised when implemented. But the exception to this rule (besides Terrain Composer) was finding the Winter Pack from Manufactura K4.

They did a fantastic job of bundling together a balanced content assortment of trees, bushes, rocks, and other winter environment elements. Everything is very high quality, aesthetically strong, and completely finished to work in Unity seamlessly. As an indie developer I greatly appreciate the promise of the asset store occasionally coming true, and saving a ton of content development time.

Populating the World

In Terrain Composer there are 3 layers of scattered content for the game:

- Trees (this includes bushes) essentially large plants
- Grasses (polygonal sprites) for small plants
- Rocks (objects) for obstacles & breaking up the player flow

For each layer I needed to create a custom mask to control the distribution of objects throughout the environment. These nature objects need to appear only on the flatter ground areas, and have varying falloff as they get closer to the ocean. The steepness mask is generated in World Machine, then post-processed to accommodate the water line.

Additionally, we need to prevent these objects from appearing on paths, or inside structures and other placed game objects. For this we can generate an Objects Mask in Terrain Composer, a fantastic time saver. The trick here is precisely registering this mask with the World Machine output. For this I created a node in the world at 0,0,0, and parent the game objects to this node so they are all considered in the mask.

Here you can see how this is all used:

Vegetation masks at work
Vegetation masks at work
An important note: Having grass displayed in Unity's editor completely kills performance. And by kills, I mean utterly smashes into oblivion. Fortunately Terrain Composer lets you set draw distances for trees & grass separately between the editor & run-time. Setting the grass distance to 0 makes the editor useable again.

For nature objects, the filters & masks in Terrain Composer work just like what I showed in the previous post on texturing. Here is the set up for the trees:

Tree distribution - filter & mask
Tree distribution - filter & mask
Chopping Down Trees

After the world was populated with natural objects, we proceeded to tackle the issue of chopping down trees. This was tricky, first because one of our talented programmers at Digital DNA needed to write a new collision system that would support the huge number of trees on the map. This made it possible work around some classic memory limit issues. A system also was required to remove trees from the world (leaving behind stumps), and making the tree top fall over.

The next challenge was getting the tree prefabs out of Unity 3D and into a 3D editor so I could create the destruction models. The best tool for this turned out the be Export2Maya, a package from Michael Cook available on the Unity asset store. It's a simple and clean interface that exports the geometry & UVs out into OBJ format. Just make sure that in Unity you center the model in the world before hitting export.

Tree testing scene in Unity 3D
Tree testing scene in Unity 3D
Once I had a tree outside of Unity, I proceeded to cut it up into pieces:

- Trunk
- Chunks (removed while chopping)
- Tree Top (part that falls over)

The hardest part of this was dealing with what happens when you cut apart a model with existing UVs. If the are any un-welded vertices or geometry wierdness, the UV's break and you have to redo them. This ended up being the case on most of the tree trunks. The challenge here is, when the trees are swapped between intact & destructable, you want zero change in appearance that would give away the switch. So new UVs have to perfectly match the original ones.

Also, a texture representing the tree interior needed to be added. Here is an exploded view of the destructable tree:

chop-able tree exploded view
chop-able tree exploded view
This had to be repeated for every tree & bush in the game, which ended up being a fair amount of work. For the smaller bushes I simplified this setup so that whacking away at it just removes partial chunks until it's gone.

I still have a problem to solve, which is a slight brightness pop when the trees swap states. Terrain Composer is set up to do some random tinting of vegetation, this makes the intact tree appear darker than the destructable tree. People see this as a lighting change, but it's most likely just the tint going away.

Thoughts & Lessons

It's worth mentioning that we apply wind to all the vegetation, but it's nowhere near the look I want yet. The trees sort of "shake & shimmy" instead of showing larger scale motion. And the grasses all move in unison, and could use more variation of motion. Both are issues I'm looking to solve in the near future.

Once again, none of this cool stuff would have seen the light of day without the incredible support & amazing minds at Digital DNA Games.


Monday, March 16, 2015

Environment in Savage Lands: Part 2 - Terrain Composer & Splat Textures in Unity 3D

Outside the village Argo
screnshot from Savage Lands

In my last post I talked about the concept phase, and the tools & procedural sculpting of our height map.

Moving to the next step of the pipeline, I will attempt to describe how we established the environment in Unity using Terrain Composer. The first stage is the terrain texture application.

Booting Up

Unity 4 already has built-in terrain & tree systems, but we were looking for a way to really maximize the treatment & organic feel of the environment space. Terrain Composer was recommended by a colleague who showed me it's unified interface that manages a complex application of textures, vegetation, and objects scattered on the terrain.

Actually using TC was quite another thing. The tool is exceptionally deep & powerful, but the majority of it is undocumented. The videos help a little, but don't go into much depth on the specifics of what every control in the interface actually does. And the interface itself isn't the pinnacle of "artist-friendly".

Here is the setup for the displacement of the terrain mesh:

Height Map setup in Terrain Composer
Height Map setup in Terrain Composer

Generating the terrain mesh was straight forward. You apply the height map texture (16-bit) to a new terrain mesh, the adjust scale and resolution. We experimented with multi-mesh (tiled) terrains for a while, but couldn't really see any advantage to that approach, in fact it made the data more complicated to manage. So we settled on one terrain mesh for the whole world.

Base Texturing

So, it took weeks of experimenting to arrive at a point where I felt I could control the output when it came to splat maps, texture blending, and layer controls. Eventually I went back and started with a stripped down scene in unity, and applying a set of test textures that were color coded and labeled with a unique number.

Then, many knobs were twiddled. Over & over again to understand filters, curves, masks, blend ranges, and how all these things interact. This really helped to see what the tool was actually doing.

The result of this research phase was the decision to use 8 texture sets for the terrain, consisting of 5 snow textures distributed by altitude (ranging from muddy snow to grassy snow to pure snow), 2 rock textures on cliffs, and 1 muddy ground texture that goes underneath villages and the water.

In each texture slot you can set the tile amount & offset under Settings. You can input a diffuse and normal texture map for each channel. I found out much later that you can put a Specular texture into the alpha of the diffuse! Never saw that in the documentation, and it made a huge difference.

Main texture index for terrain
Main texture index for terrain

Splat Maps

A "splat" map is usually an RBGA image, you store one mask into each channel for a total of 4 masks in a splat. These masks control where each texture channel is applied on the terrain. This is how Unity likes the data. Terrain Composer generates these in the final step.

But the layers are where the real power is. They let you reference a single mask texture for a given feature, and you can use 16-bit textures for this. Here are each of the layer & filter setups for our terrain textures in TC:

Snow Layer Height Curve & Mask
Snow Layer Height Curve & Mask
Cliffs with Steepness Curve
Cliffs with Steepness Curve
Paths with Mask Only
Paths with Mask Only

In the above images you can see 3 layers of application:

1) Snow - curve based on height (altitude). A filter is added with a mask to put snow only on flatter areas of the terrain.

2) Cliffs - curve based on slope steepness. The curve represents degrees, so you have to arrange your index or do some crafty curve editing to get the right texture on the right angle.

3) Paths - no curve variation, just straight application with a filter mask that was painted to localize application to village areas.

For the first layer (snow), it's important to note that the "height" curve represents the full range of a height map, so if the highest point in your height map is 0.5 luminance, you need to adjust the curve max point accordingly.

For each layer you specify the index of textures used, and set a "mix rate" which is the overlap area where two textures are blended together. This really helps provide more variation. You can also set sliders for each texture channel to bias it against the curve.

In this image you can see the Snow textures, and how the mud is pushed down to the lowest altitude so it appears only under the water.

Snow layer blending & bias
Snow layer blending & bias

Go Time

Once you've defined your textures, layers, and filters, you can generate the final splat maps and TC will apply all this to your terrain. After that we apply the global normal map which adds a lot of nice shading detail. It's crucial to bake the normals from the height map using the same overall terrain height you set in Terrain Composer.

Here is a screenshot showing how the filter masks create nice smooth blends between texture areas.

Lessons and Thoughts

Once you decode the Rubik's cube that is Terrain Composer, it becomes a really great way to manage your terrain features across a huge play area. I would love to contribute to a documentation effort that would save others the countless hours I spent arriving at sane baselines for this part of the pipeline.

There are other tools like Relief Terrain Pack (RTP) that add another level of realism to the terrain shaders & textures. We gave it a try early on, but abandoned it because the added complexity made it tough to get predictable results. Like TC, it's a powerful set of tools that require loads of time to really understand. I may revisit it at a later date, as I've seen some people get amazing results with RTP.

Next, time to fill the world with vegetation!

Part 3 - Vegetation and Chopping Down Trees

Thanks for reading!!