Due to my decision to render in unreal engine, a big step in my workflow involved getting scenes from Maya into UE5. I had been experimenting briefly throughout the entirety of production but once I had a handful of shots and the environment finalized, I began the official transition.
The first step involves creating a new level in unreal and importing the environment. Before I thought about shots, I needed to fully build the look of the environment within unreal. This meant adjusting the skybox, fog, lighting and many small universal settings that would be present for all shots.
Rebuilding the environment and rendering the first couple shots was long process, but I realized quickly that the workload was front loaded. Getting everything correct early on would mean that by the time I reached later shots, I would have an efficient system.
Rebuilding the environment in Unreal Engine was fairly straightforward. I initially tried combining all my environment meshes in Maya and exporting as a single FBX, but realised that I would have more freedom down the line if I left the meshes separate. There were several occasions where I would budge pillars or remove walls on a shot-by-shot basis to make for a better composition. This wouldn't have been possible with a combined mesh.
The church was comprised of 1,028 separate objects in total
One part of the Maya to UE pipeline I don't like is the fact that materials do not transfer. With the correct export settings, you can pack embedded media and import correctly named materials, but you still have to set up the textures manually. The only instance where materials seemed to import automatically was with the Goliath who used .tga files. This is something I might have to keep in mind for future projects.
Once the environment was imported and textured, I started populating it with additional additional UE5 assets. I added torches, statues, wall detailing and flame effects throughout the room. The torches were important because outside of the stained glass windows, there was no real source of lighting. The orange flames also complimented the blue look I was aiming for with the final film.
One thing I had completely forgot to account for throughout production was the exterior of the church. I knew there would be no shots from outside however neglected to realise that there are shots with the doors open that look out into the world. I was forced to quickly construct some sort of courtyard from Unreal Assets, using a fountain and some rocks. The heavy fog helped sell the effect.
Courtyard cobbled together from UE Assets
Effect I wanted to achieve in Unreal
Something I had hoped to achieve with my environment once it was in unreal, was realistic translucent coloured shadows through the stained glass.
Unfortunately, the global illumination setting I was using (Lumen) did not allow for such a feature, instead requiring a Lightmass or path tracing model. I did some tests using these modes and still could not get it work properly, and the visual difference in GI did not seem like a worthy trade-off.
I opted to forgo the stained glass lighting and stick with Lumen, attempting to 'mimic' the coloured lighting by shining relevant colours in through the stained glass window.
Using Colored Translucent Shadows in Unreal Engine | Unreal Engine 5.0 Documentation
As I had discovered in my initial tests, the Sylvanas character had to be exported as an FBX if I wanted to utilise the skeletal mesh cloth simulations. With the Goliath, I could technically use an alembic cache, however the other benefit of an FBX is that I can import the character into the project generally, and then apply shot specific animations for every sequence. This is far cleaner that having a separate alembic for every shot.
I used Maya's Game Exporter to export animations, mainly due to the fact that it remembers settings and file names, which made exporting files multiple times less tedious.
The master Goliath content folder
Shot_0130 bin with animation files
Scale was something I had to reconfigure once characters were moved over to Unreal. Narratively, I had decided Sylvanas was around 1.7m tall whilst the Goliath was around 3m tall. This meant that the Sylvanas rig had her root control scaled down to 0.7 whilst the goliath was scaled up by 10.2 (This was supposed to be 12 but I made a mistake and it was far too long before I noticed).
However, due to the structure of the Sylvanas rig, she did not retain her scale after the import and so her initial import scale (as well as any animation imports) had to be set to 0.7.
For some reason this did not apply to the Goliath, who had his initial import scaled up but subsequent animation imports were required to be left at a scale of 1.
First version of Shot _0020. Scaled Incorrectly
Final Shot_0020
It took me time to figure out these scaling issues, and they actual cost me a fair bit of time in correcting my mistakes. When I was bringing in many of the early shots, Sylvanas was left at a scale of 1. This would seem like an easy fix by simply scaling her down, however when I tried this, issues occurred regarding to her cloth painting and collision capsules. Therefore, I was forced to reimport her and start from scratch. That was a frustrating error...
Whilst I don't know the true cause of the scaling issues, I believe it is tied to this next issue.
With the Goliath, putting his animation into the scene at 0,0,0 would keep the global root offset and place the character exactly where he was in Maya, which was perfect as I had to do no work lining him up with the environment.
Sylvanas however, was not so simple. Regardless of the transforms on her root control, her root would always import at 0,0,0. This meant that I would have to manually ensure her root position and rotations matched the Maya scene and that she lined up with everything in the world. This was especially annoying with the original walk cycle sequence as I was forced to reanimate her root and make sure there was no sliding occurring.
I tried many methods to try and fix this issue but always came up short. From what I can understand, the problem stems from the lack of a joint on her main controller. I experimented with several solutions to try and insert a new root joint into her hierarchy however with limited rigging knowledge I ended up just breaking the rig even further.
Far too late I realised that I could have left the root control at 0,0,0 in maya and animated her off her root, which I did do for the last couple shots. But since I had already animated most of the film by the time I realised this it was too late to change.
Thankfully, the majority of the time it wasn't required for exact position to be the same and I was able to manually line things up when the situation called for it. Where it did create issues however, was regarding the methods of attaching and interacting with props... (more on that in a moment)
In a similar vein to the global position, there was another small issue that occured. Whilst the Goliath's positions were all correct, initial imports had unexpected deformations as seen in the picture to the right. Parts of his thighs were extruding out behind his body and his front belt was rotated around to the left of his body. I thought it was perhaps a glitch in the export but after several attempts it persisted.
Due to the nature of the rotated belt, I thought that there was maybe a discrepancy between the skeletal mesh's orientation and the imported animations orientation. This did turn out to be the case. The Goliaths animations were imported at a z of -90 to get him to face the correct direction, but since the original skeletal mesh had a rot z of 0, it was causing unexpected results. Reimporting the skeletal mesh with a z of -90 solved the issue.
FBX Rotation bug
When it came to exporting props there were two interactable items I needed to consider and two export options available. The Goliaths hammer is built into his rig, and so I didn't have to worry about that. The two main concerts were Sylvanas' bow and her arrows. I was faced with the options of an FBX export or an alembic cache.
My first instinct was the alembic cache, as it would bake the geo into its global positions and the characters would line up perfectly with their props. Of course it was not that simple. This was before I was aware of the scale and positioning issues with Sylvanas and so when my initial attempts didn't line up, I decided to try the alternative FBX method.
The problem with the FBX is that once again, the global positions are not retained and the prop is reverted to its root position. After some research, I discovered that this may not be as detrimental as it is with the character, thanks to a thing called "Sockets".
Alembic bow animation
Sylvanas with preview mesh sockets
Sockets are used in games to attach props to a characters joints. For a skeletal mesh, you can assign sockets to joints and attach props via the sequencer.
Here I have the socket set up for the Bow on the back, and the arrow in the quiver. The socket allows you to assign a preview asset to determine the default orientation for the prop. (for some reason I had to rotate the arrows 90 degrees in the preview, for them to appear correctly in the actual scene).
I had additional sockets on both hands. For most scenes, the prop is attached static to a single socket, however in the few scenes where the prop switches parents, I was able to key its influence in the sequencer in order to switch which socket it was attached to.
In the instance a prop leaves a characters influence, such as when Sylvanas fires the arrow, I did opt to use an alembic cache and through some fiddly work, line everything up.
One issue I faced with the FBX, that was specific to the bow, was a weird glitch that caused the string to detatch from the rest of the bow. The reason for this is unknown, though I suspect it lies in some unique deformer set up within the rig.
Thankfully, I stumbled across a solution by playing with settings. It required me to switch the additive anim type from 'none' to 'local space'.
I don't fully understand why or how this works, but I am simply grateful that it does.
Like the characters, opting for an FBX socket setup had the benefits that animations could be more easily applied to the rig without the need for a different geometry cache for every shot. For many shots, I didn't need to export the animation on the bow at all. Since the string is stationary, I could just attach the base rig to a socket and call it a day.
FBX bow with no additive anim type
Camera rig setup
When it came to cameras, exporting was once again a challenge I had to overcome. In Maya, I had decided to use a camera rig from a previous project that had the camera nested inside of a 3 curve setup. This was good for achieving cinematic camera moves, but a pain when it came to exporting the camera. Since all the transforms were performed on the curves, there was no actual animation data on the camera. Therefore I needed a way to bake the transforms onto the camera itself.
Initially, I downloaded an addon to help with this process but eventually figured out a simpler solution on my own. The process is as follows.
Parent constrain a locator to the camera. Bake the locators transforms. Go to the starting frame and unparent the camera from the rig. (either with the addon or shift P). Now parent constrain the camera to the locator and bake the transforms again. Delete the locator and export the camera as an FBX.
Importing the camera into unreal is a different process to most imports but actually straightforward. Once you are in sequencer, you click on the default shot camera and import the camera animation directly into the scene camera. It's an odd method but once I was aware, it was simple.