Skip to content

Add MetaHumans to Lyra

n8bot edited this page May 26, 2023 · 13 revisions

Introduction

Note: This is documentation of a set of instructions provided by discord user @PHalasz#4632 on Lyra Dev Net.

Install any number of MetaHumans into a Lyra Starter Game project, using live retargeting to drive animations.

The end result is not perfect — notably, the animation of the character visibly lags behind what the underlying driving animation is performing. The result is that items in the hands of the MetaHumans will float around a bit as they move.

Note: This has been alleviated in 5.2 (Except for as described in this issue)!!! Surprisingly the animations do not lag as much now — the gun is firmly planted in the character's hands. There is a bit of floating still, and the animations are less smooth.

Two methods for retargeting can be employed. The first documented method used IK retargeting, which is actually more suitable for non-like skeletons.

Another easy method, which this document has recently been updated to show, is Copy Pose From Mesh instead of IK retargeting (Retarget Pose From Mesh).

A known issue is that the longer weapons' butt stocks will clip into the shoulders of smaller MetaHumans. This is to be investigated and remedied in the future. The guide will be updated if/when this is fixed.

Blender and Send to Unreal are used to resize invisible skeletal meshes that are used to drive live retargeting of animations in Lyra.

The default invisible skeletal meshes in Lyra are only sized appropriately for the largest masculine MetaHuman body size. A new size must be created for all three feminine body heights, and two additional male body heights — 5 additional invisible skeletal meshes total.

Note:

Optionally, additional invisible skeletal meshes can be scaled in an attempt to perfectly match every one of the overweight and underweight body types — some of them have slightly different hand locations after scaling. Most weight sizes have hands that all line up, so this guide simplifies the process by only exporting for the different heights, and ignoring differences in the weights.

Prepare Blender with Send to Unreal Add-on

Install and configure the Blender Add-on.

Objectives

  1. Install Send to Unreal
  2. Create configuration template

Prerequisites

Procedure

  1. Install Send to Unreal

    Follow the official Send to Unreal Documentation — Quickstart provided by Epic.

  2. Create configuration template

    1. In blender, go to Pipeline -> Export -> Settings Dialog

      image


    2. Add paths for invis skeleton export

      /Game/Characters/Heroes/Mannequin/Meshes/
      
      /Game/Characters/Heroes/Mannequin/Animations/
      
      /Game/Characters/Heroes/Mannequin/Groom/
      

      image


      Note: This is found on the Paths tab.

    3. Check the box to enable Unreal Editor Launch Import UI

      image


      Note: This is found on the Import tab.

    4. Save settings as a template

      image


      Note: This is found on any tab.

      image


    5. Load settings template from dropdown menu

      image


      Note: This is also found on any tab.

      image


      image


Send to Unreal notes

Blender is now prepared to export asssets directly to Unreal Projects, with a template that will put the assets where the invisible skeletal meshes are in a Lyra project.

Resize invisible skeletal meshes

Export the Manny and Quinn (masculine and feminine) versions of the invisible skeletal meshes, import into blender, scale them, export them back to Unreal Editor, and rename them, one at a time.

Objectives

  1. Export invisible skeletal meshes from Lyra
  2. Import and scale FBX in blender
  3. Send scaled asset to Unreal
  4. Rename asset in Unreal Editor
  5. Repeat: import, scale, send, and rename, for each size
  6. Add tags to new meshes

Prerequisites

  • Blender with Send to Unreal Add-on
  • Lyra Starter Game Project

Procedure

  1. Export invisible skeletal meshes from Lyra

    1. In UE content browser go to /Content/Characters/Heroes/Mannequin/Meshes/ and export both _Invis meshes

      /Script/Engine.SkeletalMesh'/Game/Characters/Heroes/Mannequin/Meshes/SKM_Manny_Invis.SKM_Manny_Invis'
      
      /Script/Engine.SkeletalMesh'/Game/Characters/Heroes/Mannequin/Meshes/SKM_Quinn_Invis.SKM_Quinn_Invis'
      

      image


      image


      image


  2. Import and scale FBX in blender

    Note:

    Be careful during the scaling step. Blender seems very sensitive to clicking the wrong thing, and having trouble re-selecting the thing we want to scale.

    When the mesh is first imported into blender, everything we want to scale is selected. Immediately proceed with the scaling step without clicking or doing anything else.

    1. In a new blender scene, delete the starting cube (press delete key on keyboard)

    2. Go to File -> Import -> FBX (.fbx)

      Choose the previously exported SKM_Manny_Invis.FBX and accept the default import settings.

    3. Locate the Transform | Scale section that appears in the bottom right

      image


    4. Input a value of 0.955 for all axes: X, Y, and Z and press Enter(Return) on the keyboard

      This is the scaling used when going from UE5_Manny to the masculine medium height MetaHuman.

    5. Without clicking or deselecting anything, hover the mouse over the 3D viewport, press CTRL+A on the keyboard, and click Scale

      image


      Note:

      This step is crtical — make sure the scale is applied — the smaller size of the on-screen objects should be retained, but the values in the transform box will now display 1.0 because the scaling has been baked into the mesh coordinates. If the viewport is clicked, and the scene selection is changed, this step will not work.

  3. Send scaled asset to Unreal

    1. In the top right scene hiearchy, click and drag the entire imported asset to the Export collection

      image


    2. Go to Pipeline -> Utilities -> Start RPC Servers

      image


    3. Load the settings template from the dropdown menu in Pipeline -> Export -> Settings Dialog

    4. Go to Pipeline -> Export -> Push Assets

      image


    5. Go to Unreal Editor and locate the FBX Import window

      image


      Note:

      Ensure the skeleton is set to SK_Mannequin as shown.

      If this window does not appear, then likely the settings template was not loaded in Blender/Send to Unreal.

    6. Uncheck the box for Create Physics Asset

      image


    7. Select Do Not Create Material for Material Import Method

      image


    8. Uncheck the box for Import Textures

      image


    9. Click Import All on the FBX Import dialog

  4. Rename asset in Unreal Editor

    1. Rename the newly imported skeletal mesh from the content browser

      image


      For this scaling (0.955) name the asset SKM_Manny_Invis_MHMedium

      image


  5. Repeat: import, scale, send, and rename, for each size

    1. Repeat the steps above

      Create a new blender scene, delete cube, import FBX, scale, export, rename, for each gender presentation/height/weight combination according to the following table:

      SKM_Manny_Invis (masculine) SKM_Quinn_Invis (feminine)
      Tall Scale: 1.0
      Filename: (N/A)
      Scale: 0.934
      Filename: SKM_Quinn_Invis_MHTall
      Medium Scale: 0.955
      Filename: SKM_Manny_Invis_MHMedium
      Scale: 0.8825
      Filename: SKM_Quinn_Invis_MHMedium
      Short Scale: 0.915
      Filename: SKM_Manny_Invis_MHShort
      Scale: 0.84
      Filename: SKM_Quinn_Invis_MHShort

      image


      Note: These values were discovered by lining up the Manny and Quinn meshes with MetaHumans — feel free to experiment with different values.

  6. Add tags to new meshes

    1. In the Unreal Editor content browser, find and edit B_MannequinPawnCosmetics

      /Script/Engine.Blueprint'/Game/Characters/Cosmetics/B_MannequinPawnCosmetics.B_MannequinPawnCosmetics'
      
    2. Expand the Cosmetics -> Body Meshes -> Mesh Rules section

      image


      image


    3. Click the + circle icon to add 6 more Array elements — there should be 8 in total

    4. Click the dropdown menu to add a new mesh reference to SKM_Manny_Invis

      image


    5. Click the Edit... dropdown menu for Required Tags and select the Cosmetic.AnimationStyle.Mascuiline tag

      image


    6. Click the arrow beside Add New Gameplay Tag

      image


    7. Input the following into the name field:

      Cosmetic.BodyStyle.MHTall
      
    8. Click Add New Tag

    9. Repeat adding meshes and tags according to the following table

      Mesh Cosmetic.AnimationStyle Cosmetic.BodyStyle
      SKM_Manny_Invis .Masculine .MHTall
      SKM_Manny_Invis_MHMedium .Masculine .MHMedium
      SKM_Manny_Invis_MHShort .Masculine .MHShort
      SKM_Quinn_Invis_MHTall .Feminine .MHTall
      SKM_Quinn_Invis_MHMedium .Feminine .MHMedium
      SKM_Quinn_Invis_MHShort .Feminine .MHShort

      Note: The two original entries from Lyra can also remain, with their original tags.

Invisible skeletal meshes notes

All invisible skeletal meshes are now imported into the UE project. Blender can be closed.

Configure MeatHumans

Configure MeatHumans for use with live retargeting.

Objectives

  1. Enable Live Retargeting in MetaHuman Blueprint
  2. Reparent MetaHuman Blueprint to LyraTaggedClass
  3. Add tags to MetaHuman Blueprint
  4. Repeat for each MeatHuman

Prerequisites

Procedure

  1. Enable Live Retargeting in MetaHuman Blueprint

    1. Open the first MetaHuman Blueprint in Unreal Editor

      Note: Use the content browser's search/filter tool to easily navigate the folders and files.

    2. On the right side, in the Details panel, Check the box for Use Live Retarget Mode

      image


      image


  2. Reparent MetaHuman Blueprint to LyraTaggedClass

    1. In the Blueprint Editor, go to File -> Reparent Blueprint and choose LyraTaggedActor

      image


  3. Add tags to MetaHuman Blueprint

    1. In the Details panel, add the tags to the Static Gameplay Tags section

      image


      Note: Choose the tags based on the MetaHuman's gender presentation and height.

  4. Repeat for each MeatHuman

    1. Go through each MetaHuman Blueprint one by one repeating the above steps

MeatHuman configuration notes

All MetaHumans are now prepared for use with live retargeting.

Adjustments

The hand placement of the metahumans on the weapons needs to be corrected slightly.

The LOD settings used by the MetaHumans is not quite suited to the third-person camera of Lyra — LOD0/1/2 are switching too much.

Objectives

  • (Method 1) Enable Copy Pose From Mesh
  • (Method 2) Adjust hand IK target offsets and rotations
  • Adjust LOD settings
  • Fix HairStrands packaging
  • (Optional) Enable Allow CPUAccess to all MetaHuman skeletal meshes
  • (Optional) Fix Hair Card/Helmet material colour

Prerequisites

  • Lyra Starter Game Project
  • MetaHumans configured for retargeting

Procedure

  1. (Method 1) Enable Copy Pose From Mesh

    1. Go to \Content\MetaHumans\Common\Common\ and edit the file RTG_metahuman_base_skel_AnimBP.RTG_metahuman_base_skel_AnimBP

      /Script/Engine.AnimBlueprint'/Game/MetaHumans/Common/Common/RTG_metahuman_base_skel_AnimBP.RTG_metahuman_base_skel_AnimBP'
      
    2. Replace the Retarget Pose From Mesh node with a Copy Pose From Mesh node

      image


      Note: The checked boxes on the left are not required but may help in the future...

  2. (Method 2) Adjust hand IK target offsets and rotations

    Note: This method is not needed for Lyra->MetaHuman, because Copy Pose From Mesh is more performant.

    1. Go to \Content\MetaHumans\Common\Common\ and edit the file RTG_metahuman

      /Script/IKRig.IKRetargeter'/Game/MetaHumans/Common/Common/RTG_metahuman.RTG_metahuman'
      
    2. Reset the pose in the IK retargeter

      image


      Note:

      This was causing problems with IK hand alignment, because the reference pose was not the natural Mannequin/MetaHuman pose. Make sure when you blend from 0.0 to 1.0 on that slider, the pose doesn't change much, if at all. The arms shouldn't flap up and down.

      A previous version of this guide neglected to reset this difference in reference pose, and the subsequent offset figures given are now invalid. If you need to use IK retargeting offsets, follow the gist of these steps below and discover your own offset values for your specific needs.

    3. On the bottom right corner in the Chain Mapping panel select LeftArm

      image


    4. Edit the left hand goals as desired

      Set Blend to Source to 0.0.

      X Y Z
      Static Local Offset 0.0 0.0 0.0
      Static Rotation Offset 0.0 0.0 0.0

      image


      Note: These values are out of date and shown just for illustration — use Blend to Source = 0.0.

    5. Edit the right hand goals as follows

      Set Blend To Source to 0.0.

      X Y Z
      Static Local Offset 0.0 0.0 0.0
      Static Rotation Offset 0.0 0.0 0.0

      image


      Note: These values are out of date and shown just for illustration — use Blend to Source = 0.0.

  3. Adjust LOD settings

    1. Go to \Content\MetaHumans\Common\Face\ and edit Face_Archetype_LODSettings

      /Script/Engine.SkeletalMeshLODSettings'/Game/MetaHumans/Common/Face/Face_Archetype_LODSettings.Face_Archetype_LODSettings'
      
    2. Change the following settings

      LOD Index Screen Size
      Index[1] 0.2
      Index[2] 0.14
      Index[3] 0.12667
      Index[4] 0.11333

      image


      Note: Change all LOD indices as noted above.

  4. Fix HairStrands packaging

    1. In Windows Explorer, go to the project folder \Echelons\Config\ and edit the file DefaultGame.ini

    2. Add the following line

      +DirectoriesToAlwaysCook=(Path="/HairStrands")
      

      image


  5. (Optional) Enable Allow CPUAccess to all MetaHuman skeletal meshes/LODs

    This will enable the dash niagara blur effects for the MetaHumans.

    1. Use the content browser to filter for all skeletal meshes in the \MetaHumans\ directory

    2. Use the Bulk Edit via Property Matrix to edit multiple meshes at once

      image


      Note: This will be a slow process. Select only a subset of the meshes at one time to speed things up.

      image


  6. (Optional) Fix Hair Card/Helmet material colour

    See this tutorial on fixing hair material for higher LOD indices.

    Default lit; Scraggle=1.5 for all hair cards and helmet material instances.

Adjustment notes

MetaHumans are fully configured and ready to be used.

Replace Manny and Quinn with MeatHuman(s)

There are a couple ways to play as a MeatHuman in Lyra.

Objectives

  1. Use developer cheats to test MetaHuman in-editor only
  2. Replace/Add MeatHumans to Lyra random character selection

Prerequisites

  • Everything in this guide

Procedure

  1. Use developer cheats to test MetaHuman in-editor only

    1. In Unreal Editor go to Edit -> Editor Preferences...

    2. Navigate to the Lyra Cosmetic Developer Settings section

    3. Under Cheat Cosmetic Character Parts click the + circle icon

      image


    4. Select the desired MetaHuman Blueprint in the Part Class dropdown menu

      image


      The selected MeatHuman will now replace Manny and Quinn in PIE.

  2. Replace/Add MeatHumans to Lyra random character selection

    1. Go to \Content\Characters\Cosmetics and edit B_PickRandomCharacter

      /Script/Engine.Blueprint'/Game/Characters/Cosmetics/B_PickRandomCharacter.B_PickRandomCharacter'
      
    2. Add an array variable of Actor Class References with all your MeatHuman Blueprints as the default values

    3. Modify the EventGraph like so:

      image


      Copy and Paste the following into the Blueprint window and connect as shown.

      Begin Object Class=/Script/BlueprintGraph.K2Node_VariableGet Name="K2Node_VariableGet_0"
         VariableReference=(MemberName="Meathumans",MemberGuid=A017142044B33FD7F80D519E7CA2E65F,bSelfContext=True)
         NodePosX=144
         NodePosY=112
         NodeGuid=421791E44629172CD2BB09BF51EBAFB0
         CustomProperties Pin (PinId=FFBDB1D64AF1033BD0F0B3A3E780F73F,PinName="Meathumans",Direction="EGPD_Output",PinType.PinCategory="class",PinType.PinSubCategory="",PinType.PinSubCategoryObject=/Script/CoreUObject.Class'"/Script/Engine.Actor"',PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=Array,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallArrayFunction_2 BF8F6C544A51640C5F077CBC3B752C69,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
         CustomProperties Pin (PinId=04CA91AE488562626D9670B8B07C9102,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject=/Script/Engine.BlueprintGeneratedClass'"/Game/Characters/Cosmetics/B_PickRandomCharacter.B_PickRandomCharacter_C"',PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
      End Object
      Begin Object Class=/Script/BlueprintGraph.K2Node_CallArrayFunction Name="K2Node_CallArrayFunction_2"
         bIsPureFunc=True
         FunctionReference=(MemberParent=/Script/CoreUObject.Class'"/Script/Engine.KismetArrayLibrary"',MemberName="Array_Random")
         NodePosX=352
         NodePosY=96
         NodeGuid=F082FBD848FF1CA1D19D26B3AE5027B5
         CustomProperties Pin (PinId=363AB29E480ACAF119D2A89B8DE2D6F9,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nKismet Array Library Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject=/Script/CoreUObject.Class'"/Script/Engine.KismetArrayLibrary"',PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Engine.Default__KismetArrayLibrary",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
         CustomProperties Pin (PinId=BF8F6C544A51640C5F077CBC3B752C69,PinName="TargetArray",PinToolTip="Target Array\nArray of Actor Class References\n\nThe array",PinType.PinCategory="class",PinType.PinSubCategory="",PinType.PinSubCategoryObject=/Script/CoreUObject.Class'"/Script/Engine.Actor"',PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=Array,PinType.bIsReference=True,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_VariableGet_0 FFBDB1D64AF1033BD0F0B3A3E780F73F,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=True,bAdvancedView=False,bOrphanedPin=False,)
         CustomProperties Pin (PinId=DFFACD854E4901A44A79C3A7B0A68F51,PinName="OutItem",PinToolTip="Out Item\nActor Class Reference\n\nThe random item from this array",Direction="EGPD_Output",PinType.PinCategory="class",PinType.PinSubCategory="",PinType.PinSubCategoryObject=/Script/CoreUObject.Class'"/Script/Engine.Actor"',PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_0 CC6FF92A42DD32B828A0BD8331436E15,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
         CustomProperties Pin (PinId=2B952A43426F17FA96F5689004528D63,PinName="OutIndex",PinToolTip="Out Index\nInteger\n\nThe index of random item (will be -1 if array is empty)",Direction="EGPD_Output",PinType.PinCategory="int",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0",AutogeneratedDefaultValue="0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
      End Object
      

      A random MeatHuman will be spawned for each player or bot.

Implemtnation notes

It's not perfect, but it works.

Final Notes

All Done!