Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

UMA - Unity Multipurpose Avatar on the Asset Store!

Discussion in 'Assets and Asset Store' started by FernandoRibeiro, Dec 24, 2013.

  1. colpolstudios

    colpolstudios

    Joined:
    Nov 2, 2011
    Posts:
    150
    This also may be an option: https://github.com/edk208/mixamoFaceTransfer
     
    Zante likes this.
  2. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    Definitely curious about learning more. The fact that it is open source and automatically generates the blendshapes makes this approach a contender against services like PolyWink - which costs an absolute fortune to use. This gives me hope that UMA will integrate similar functionality in the future.
     
  3. colpolstudios

    colpolstudios

    Joined:
    Nov 2, 2011
    Posts:
    150
    Yeah, but getting it to work is beyond my abilities. But all of the information is there to set it up. Im just terrified to try.
     
  4. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    Michael Berna was generous enough to let me use this peasant clothing set in the AnyRPG Engine! AFAIK this makes it the only free clothing set of UMA armor on the entire Internet that is not part of the UMA Unity package samples (challenger / mystic)!

    I posted a video so you can see what it looks like in use :)

     
    boysenberry likes this.
  5. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    Do you get an error in the console?
     
  6. vamosfa

    vamosfa

    Joined:
    May 15, 2016
    Posts:
    59
    Hi, I saw all youtube videos and read the documentation but I am not finding what I need: saving .fbx UMA characters to edit them in Blender. A lot of videos and explanations about the opposite direction: DAZ, Fuse, Blender, etc...to UMA, but not from UMA to Blender. I take into account that youtube videos were recorded years ago before Unity had .fbx exporter package available, so, maybe it is possible now. Can someone please help me? Thank you.
     
  7. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    UMA is designed to be a runtime solution. For exporting, this is only available via a 3rdparty solution:

    https://assetstore.unity.com/packages/tools/modeling/unity-fbx-exporter-69997
     
  8. vamosfa

    vamosfa

    Joined:
    May 15, 2016
    Posts:
    59
    Thanks for replying. Maybe the question could be obvious, but considering the price of the asset I prefer to be very sure before purchasing it: FBX Exporter Package from Package Manager can not do that? The limitation is exporting things in Runtime?
     
  9. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    I have tried several times with the free exporter from Unity. I was able to get a 2.03 to export to FBX after modifying the code, and configuring the UMAGenerator to copy the rendertextures. The main issue is that UMA generates materials and atlases on the fly, and the Unity FBX code expects these to exist in the project. It's not an insurmountable issue if you want to tinker with their export package.
     
    vamosfa likes this.
  10. vamosfa

    vamosfa

    Joined:
    May 15, 2016
    Posts:
    59
    I see. In my case, I only need the mesh, so it would not a problem to not have the materials or textures, so I will think about that considering the exporting result.
     
  11. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    You'll need to work around some parts of the code where it expects the materials to exist, but it's doable.
     
  12. vamosfa

    vamosfa

    Joined:
    May 15, 2016
    Posts:
    59
    Hi, I managed to do so with default .fbx exporter from Unity to Blender 2.83, and the result is perfect. Just the mesh as I told you. I did not need to touch any code. I exported the DynamicAvatar1 autogenerated by UMA in Runtime, choosing Bynary as Export format. In Blender I deleted all the bone hierarchy. That´s all. This how it looks:
    UMAPreset.png
     
  13. ABB13

    ABB13

    Joined:
    Apr 23, 2018
    Posts:
    82
    Hi, I created this character in blender but I don't understand why it's possible to see throught him when I use it with UMA (on the right I put the simple 3D model to see if it was a mesh problem). Can anyone help me?
     

    Attached Files:

  14. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    It looks like the normals are inverted. This can be caused by having a negative scale on a bone. Be sure you have applied all the bone transformations in pose mode, they must be normalized to work correctly. You will also need to re-extract the t-pose.
     
    hopeful likes this.
  15. ABB13

    ABB13

    Joined:
    Apr 23, 2018
    Posts:
    82
    Ty for the reply, I'm will try it
     
  16. ABB13

    ABB13

    Joined:
    Apr 23, 2018
    Posts:
    82
    I cleared all the transform and I applied the transformations in "pose position" tab. I have also re-extracted the t-pose but nothing is changed :/ .
    The only thing that I did different was my character starting position and it wasn't in T-mode, could this be the problem?

    P.S. I tried to set my character pose to T-Pose from mixamo and I fixed all the transformations, but I still I have the same problem. Maybe I missed something or I did bad the thing that u saied
     
    Last edited: Sep 2, 2020
  17. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    340
    How can I bypass using the UMA global library?
    Right now my memory usage is hovering over 6.5 GB
    And when I drilled into the profiler I see all the textures for my UMA characters loaded into memory.
    After a lot of searching I realized that this must be due to the UMA global library.
    I have changed my entire project to use Addressables, but not sure how to tackle this UMA problem.
     
  18. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    Once you have enabled addressables support in the UMA preferences, run the option in the global lib menu to generate the addressable groups. Then build the bundles. UMA will then demand load the overlays/textures/slots as needed, and unload them when they are not needed.
     
    Zante and hopeful like this.
  19. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    At this point, I have no idea. If you can send me the blend via IM, I can take a look at it.
     
  20. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    340
    I just downloaded the 2.10 version and the global library is so laggy I can't really do anything.
     
  21. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    If you have a lot of assets in the library, Unity will load them all. You can get around this by using Addressables.
     
  22. Buka

    Buka

    Joined:
    Feb 22, 2013
    Posts:
    48
    Hi, we have another issue and i need help how to fix it:
    Each time a recipe is clicked there are these warnings and they are annoying indeed:

    DynamicUMADna could not find DNAAsset HumanFemaleDNA 1!
    Deserialized DynamicUMADna with no matching asset!

    We did change DNA, removed things we don't need but how can i get rid of these warnings and how to match dna or whatever i need to do? Every recipe has this and we have a lot of them.

    Thanks!
     

    Attached Files:

  23. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    340
    Jaimi thanks for your help.
    I was able to get the addressables in the global libarary and had it create the group.
    upload_2020-9-3_8-6-28.png
    I then built the group and tried to play but I can getting this error:

    UMAResourceNotFoundException: dSlotLibrary (211): Unable to find: Female_Eyes_Apoth
    UMA.CharacterSystem.DynamicSlotLibrary.InstantiateSlot (System.String name) (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicSlotLibrary.cs:170)
    UMA.UMAContext.InstantiateSlot (System.String name) (at Assets/UMA/Core/StandardAssets/UMA/Scripts/UMAContext.cs:164)
    UMA.UMAPackedRecipeBase.UnpackRecipeVersion3 (UMA.UMAData+UMARecipe umaRecipe, UMA.UMAPackedRecipeBase+UMAPackRecipe umaPackRecipe, UMA.UMAContextBase context) (at Assets/UMA/Core/Scripts/UMAPackedRecipeBase.cs:947)
    UMA.UMAPackedRecipeBase.UnpackRecipe (UMA.UMAData+UMARecipe umaRecipe, UMA.UMAPackedRecipeBase+UMAPackRecipe umaPackRecipe, UMA.UMAContextBase context) (at Assets/UMA/Core/Scripts/UMAPackedRecipeBase.cs:35)
    UMA.UMAPackedRecipeBase.Load (UMA.UMAData+UMARecipe umaRecipe, UMA.UMAContextBase context) (at Assets/UMA/Core/Scripts/UMAPackedRecipeBase.cs:20)
    UMA.UMATextRecipe.Load (UMA.UMAData+UMARecipe umaRecipe, UMA.UMAContextBase context) (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/pUMATextRecipe.cs:189)
    UMA.CharacterSystem.DynamicCharacterAvatar.LoadCharacter (UMA.UMARecipeBase umaRecipe, System.Collections.Generic.List`1[T] Replaces, System.Collections.Generic.List`1[T] umaAdditionalSerializedRecipes, UMA.UMARecipeBase[] AdditionalRecipes, System.Collections.Generic.Dictionary`2[TKey,TValue] MeshHideDictionary, System.Collections.Generic.List`1[T] hiddenSlots, System.Collections.Generic.List`1[T] HideTags, UMA.UMADnaBase[] CurrentDNA, System.Boolean restoreDNA, System.Boolean skipBundleCheck) (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicCharacterAvatar.cs:3165)
    UMA.CharacterSystem.DynamicCharacterAvatar.BuildCharacter (System.Boolean RestoreDNA, System.Boolean skipBundleCheck) (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicCharacterAvatar.cs:2996)
    UMA.CharacterSystem.DynamicCharacterAvatar.BuildFromComponentSettings () (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicCharacterAvatar.cs:559)
    UMA.CharacterSystem.DynamicCharacterAvatar.Start () (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicCharacterAvatar.cs:421)


    Any ideas on what I am missing?
     
  24. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    340
    I checked the group and I do see it:
    upload_2020-9-3_8-10-10.png
    Is it because the address is "UMA/SlotDataAsset-Female_Eyes_Apoth" but it is looking for "Female_Eyes_Apoth"?
     
  25. arteria

    arteria

    Joined:
    May 31, 2007
    Posts:
    2,189
  26. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    First - it appears you are using the old prefab. You need to switch to use the UMA_GLIB prefab, as documented in the "Upgrading to 2.10 from a previous version - Read Me Now" file.
    Also, it appears your DCA is not waiting for bundles to load. Make sure you did not turn off "Bundle Check" on the DCA.

     
    hopeful likes this.
  27. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    No. Slots are looked up by "Slot Name" in the library, not by the name of the object.
     
  28. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    340
    I got it working thanks for the help.
     
    hopeful likes this.
  29. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    I'm seeing a lot of conflicting information regarding how to export FBX files from UMA to be used in animation workflows.

    What is the most reliable method of exporting a dynamically created character as an FBX currently in Unity 2018.4.11f1 and UMA 2.10.1? :[

    Additionally, I've been experimenting with some facial motion capture using a webcam and the results on the bones I targeted seemed to work well. The problem is that in the dynamically created character, the jaw/mandible ins't moving.

    Can anyone think why?

    You can see the placeholder model moving their jaw for the same animation, which is humanoid in composition.

     
    Last edited: Sep 4, 2020
  30. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    340
    I am getting 3 errors after changing scenes.
    All errors are the same.

    MissingReferenceException: The object of type 'DynamicCharacterAvatar' has been destroyed but you are still trying to access it.
    Your script should either check if it is null or you should not destroy the object.
    UnityEngine.Component.GetComponent[T] () (at <ee47be73f7ef409ca5e5ce4b121745b7>:0)
    UMA.UMAAvatarBase.Initialize () (at Assets/UMA/Core/StandardAssets/UMA/Scripts/UMAAvatarBase.cs:65)
    UMA.CharacterSystem.DynamicCharacterAvatar.LoadCharacter (UMA.UMARecipeBase umaRecipe, System.Collections.Generic.List`1[T] Replaces, System.Collections.Generic.List`1[T] umaAdditionalSerializedRecipes, UMA.UMARecipeBase[] AdditionalRecipes, System.Collections.Generic.Dictionary`2[TKey,TValue] MeshHideDictionary, System.Collections.Generic.List`1[T] hiddenSlots, System.Collections.Generic.List`1[T] HideTags, UMA.UMADnaBase[] CurrentDNA, System.Boolean restoreDNA, System.Boolean skipBundleCheck) (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicCharacterAvatar.cs:3150)
    UMA.CharacterSystem.DynamicCharacterAvatar.LoadWhenReady (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject] Op) (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicCharacterAvatar.cs:3036)
    UnityEngine.Debug:LogException(Exception, Object)
    UMA.CharacterSystem.DynamicCharacterAvatar:LoadWhenReady(AsyncOperationHandle`1) (at Assets/UMA/Core/Extensions/DynamicCharacterSystem/Scripts/DynamicCharacterAvatar.cs:3054)
    DelegateList`1:Invoke(AsyncOperationHandle`1) (at Library/PackageCache/com.unity.addressables@1.8.5/Runtime/ResourceManager/Util/DelegateList.cs:69)
    UnityEngine.ResourceManagement.ChainOperation`2:OnWrappedCompleted(AsyncOperationHandle`1)
    DelegateList`1:Invoke(AsyncOperationHandle`1) (at Library/PackageCache/com.unity.addressables@1.8.5/Runtime/ResourceManager/Util/DelegateList.cs:69)
    UnityEngine.ResourceManagement.ResourceManager:Update(Single)
    MonoBehaviourCallbackHooks:Update() (at Library/PackageCache/com.unity.addressables@1.8.5/Runtime/ResourceManager/Util/MonoBehaviourCallbackHooks.cs:19)
     
  31. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    The only method that currently works that I'm aware of is the Unlogick exporter.

    A page back or so, someone had some luck with the Unity FBX exporter, but it did not bring in the atlas textures, and the skeleton was all messed up on import, but they did not need either of those.
    There's probably some combination of manual orientation and Armature Primary/Secondary bone axis that would make it work, but I haven't figured it out yet.

    As for your jaw not moving - there is a version of the T-Pose that has the avatar jaw mapped, and one that doesn't. This is because if the jaw is mapped in the avatar, and you do not animate the jaw bone, then the avatar opens their mouth like a dead fish. Make sure the race you are using has the jaw mapped. I'm not sure if the "mecanim friendly" version of the tpose has the jaw mapped or not. It really should, but it may not.


     
    Zante likes this.
  32. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    It looks like your UMA has been destroyed. This usually happens when scenes change, unless you specifically tell unity to keep the object by setting "DontDestroyOnLoad" on an object.

     
  33. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    Thanks for this. Does anyone have a definite answer regarding which FBX I should be animating in order to faithfully convey bone-driven facial animation?
     
  34. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    The unified mesh FBX files are included in UMA - UMA/Content/Core/HumanFemale/FBX (etc).

    Or if you are a blender user, you can use the source files from the content pack here:

    https://github.com/umasteeringgroup/content-pack
     
    Zante and hopeful like this.
  35. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    The more I experiment, the more I think I'm going about this wrongly. I've just realised that the "FacialAnimationDemo" is actually controlling values in the expression player script rather than effecting the bones directly.

    I've been using FaceWare studio's trial to explore facial motion capture and, while the results are very promising, the workflow is awful (doesn't seem to work in the same project as UMA and bone based animation from scratch is a massive headache).

    So, building on the shoulders of giants, my current strategy is as follows...

    There's a tool on the asset store called Polyphemus which provides an in-situ (from inside the Unity editor) means of capturing facial animation via a webcam. At the moment, it works based on blendshape parameters but, mathematically, I don't see any reason why retargeting the blendshapes it's looking for to the ready-made poses in the UMA expression player wouldn't also work.



    This seems like the most obvious solution to me. I've left a message in the thread for Polyphemus but don't have time to get fully acquainted with their tool to invest in experimentation myself. The other possibility is Humanoid Pro from PasserVR. I've been in touch with the author to see if their bone-based animator can be updated to work with UMA (Microsoft Kinect 2 required however).

    It's hard to say which of the three here will yield the best results for facial mocap workflows in UMA but they're the most viable starting points I've seen so far. If anyone has dabbled in this sort of thing (UMA facial mocap), we really need all the information we can get.
     
    Last edited: Sep 6, 2020
  36. Buka

    Buka

    Joined:
    Feb 22, 2013
    Posts:
    48
  37. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    The earlier save scripts needed the DNA type in order to match the DNA. This is saved in the recipe string. The error is telling you that the specific DNA there no longer exists, but you have DNA defined in the string that uses it. I think the easiest thing to do is to load the strings and resave them.
     
  38. cobaltBlue

    cobaltBlue

    Joined:
    Oct 25, 2011
    Posts:
    39
    Has anyone tried integrating Facial AR from Unity's ARFoundation/ARKit to let the user compose a UMA expression from the blend shapes provided by the AR foundation API? Should I be trying to get the blend shape values to manipulate UMA's expression player or should I just be setting the blend shape values for the UMA model directly?
     
  39. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    I'm starting to think that UMA needs this ability to interface with blendshapes, even if they exist as fake data that allows it to map values to the expression player in realtime. This would solve most, if not all, of the integration problems. Until then, everyone will need to write unique retargeting code for whatever animation solutions they want to use that only support blendshapes.
     
  40. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    UMA's expression player does not use Blendshapes - it manipulates the head rig. You can create Blendshapes on the UMA head for expressions, and drive them with some other utility, but it won't work with the expression player.
     
  41. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    Blendshapes are notorious memory hogs. But facial blendshapes would not be that big a deal. Beyond the extra memory usage, of course. Someone, with a bit of elbow-grease, could take the existing UMA model from the content pack, and create shapekeys for the needed blendshapes on the UMA heads (there's an animation included that contains all the expressions), and recreate the slots with Blendshapes included. Just be aware that Blendshapes do not affect the bones, and thus any additional slots like hair/ears, etc, so they would need to limit the blendshapes to just facial expressions.
     
  42. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    In principle, I'm suggesting that the blendshapes in this instance are not real. They would only exist to fool the editor and to allow existing solutions to detect and interface with those parameters in order to transfer values. A dedicated script would then map those fake blendshape values to the expression player.

    Is that viable? I have to admit I don't know what it would take to fool the editor into believing the UMA character had the blendshapes in question. This would, theoretically, deal with the memory overhead while allowing for the same functionality.
     
    Last edited: Sep 7, 2020
  43. marlonkewaldar

    marlonkewaldar

    Joined:
    Feb 13, 2019
    Posts:
    2
    Hello everyone,

    I'm developing a mechanic wherein I need an UMA character to change appearances based on one of three buttons the player clicks. Each of these buttons is to load in a different type of textfile in which the appearances is saved (via the UMA->SAVE/LOAD thing).

    However, I can't seem to load the resource in properly. My code is as followed:

    myRecipe = File.ReadAllText(outfit1.text);
    avatar.ClearSlots();
    avatar.LoadFromRecipeString(myRecipe);

    Where outfit1 is a TextAsset object linking to a plain old textfile containing the character appearance. However, upon clicking the button during runtime, I get the following error:

    ArgumentException: Illegal characters in path.
    System.IO.Path.GetFileName (System.String path) (at <fb001e01371b4adca20013e0ac763896>:0)
    System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding, System.Boolean detectEncodingFromByteOrderMarks, System.Int32 bufferSize, System.Boolean checkHost) (at <fb001e01371b4adca20013e0ac763896>:0)

    It seems this may not be the right way to load in a recipe, or there's another issue at play. Any ideas?
     
  44. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    I've written a brute force script that creates Blend Shapes when applied to the SkinnedMeshRender using dummy data and then pipes them back to UMA's expression player - I've yet to try this with facial motion capture but it should work.



    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UMA;
    5. using UMA.CharacterSystem;
    6. using UMA.PoseTools;
    7.  
    8. //When attached to the skinned mesh renderer object in UMA, this script creates dummy blendshapes and uses the values to control the expression player script
    9. //Use cases: When an UMA workflow requires blendshapes rather than bones to work
    10.  
    11. public class UMABlendShapeExpressions : MonoBehaviour
    12. {
    13.     public SkinnedMeshRenderer targetSkinnedRenderer;
    14.     public Mesh bakedMesh;
    15.     public UMAExpressionPlayer expressionPlayer;
    16.  
    17.     void Start()
    18.     {
    19.      
    20.         if(this.transform.parent.GetComponent<UMAExpressionPlayer>() == null)
    21.         {
    22.             Debug.Log("Please ensure an expression player has been added to the parent UMA GameObject - this script will now stop running");
    23.                 return;
    24.         }
    25.         else
    26.         {
    27.             expressionPlayer = this.transform.parent.GetComponent<UMAExpressionPlayer>();
    28.         }
    29.  
    30.         targetSkinnedRenderer = this.GetComponent<SkinnedMeshRenderer>(); //
    31.         bakedMesh = new Mesh();
    32.        
    33.         targetSkinnedRenderer.BakeMesh(bakedMesh);
    34.  
    35.         Vector3[] junkData = new Vector3[bakedMesh.vertices.Length];
    36.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Neck Up/Down", 100, junkData, junkData, junkData);
    37.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Neck Turn Left/Right", 100, junkData, junkData, junkData);
    38.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Neck Tilt Left/Right", 100, junkData, junkData, junkData);
    39.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Head Up/Down", 100, junkData, junkData, junkData);
    40.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Head Left/Right", 100, junkData, junkData, junkData);
    41.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Head Tilt Left/Right", 100, junkData, junkData, junkData);
    42.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Jaw Open/Close", 100, junkData, junkData, junkData);
    43.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Jaw Forward/Back", 100, junkData, junkData, junkData);
    44.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Jaw Left/Right", 100, junkData, junkData, junkData);
    45.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Mouth Left/Right", 100, junkData, junkData, junkData);
    46.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Mouth Up/Down", 100, junkData, junkData, junkData);
    47.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Mouth Narrow/Pucker", 100, junkData, junkData, junkData);
    48.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Tongue Out", 100, junkData, junkData, junkData);
    49.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Tongue Curl", 100, junkData, junkData, junkData);
    50.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Tongue Up/Down", 100, junkData, junkData, junkData);
    51.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Tongue Left/Right", 100, junkData, junkData, junkData);
    52.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Tongue Wide/Narrow", 100, junkData, junkData, junkData);
    53.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Mouth Smile/Frown", 100, junkData, junkData, junkData);
    54.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Mouth Smile/Frown", 100, junkData, junkData, junkData);
    55.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Lower Lip Up/Down", 100, junkData, junkData, junkData);
    56.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Lower Lip Up/Down", 100, junkData, junkData, junkData);
    57.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Upper Lip Up/Down", 100, junkData, junkData, junkData);
    58.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Upper Lip Up/Down", 100, junkData, junkData, junkData);
    59.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Cheek Puff/Squint", 100, junkData, junkData, junkData);
    60.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Cheek Puff/Squint", 100, junkData, junkData, junkData);
    61.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Nose Sneer", 100, junkData, junkData, junkData);
    62.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Eye Open/Close", 100, junkData, junkData, junkData);
    63.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Eye Open/Close", 100, junkData, junkData, junkData);
    64.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Eye Up/Down", 100, junkData, junkData, junkData);
    65.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Eye Up/Down", 100, junkData, junkData, junkData);
    66.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Eye In/Out", 100, junkData, junkData, junkData);
    67.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Eye In/Out", 100, junkData, junkData, junkData);
    68.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Brows In/Out", 100, junkData, junkData, junkData);
    69.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Left Brow Up/Down", 100, junkData, junkData, junkData);
    70.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Right Brow Up/Down", 100, junkData, junkData, junkData);
    71.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("[UMAExpressionPlayer] Mid Brow Up/Down", 100, junkData, junkData, junkData);
    72.         //Mesh.GetBlendShapeFrameVertices.del;
    73.         ResetUMABlendShapes(50);//the value to set the blendshapes to
    74.     }
    75.  
    76.     public void ResetUMABlendShapes(int value)
    77.     {
    78.         int blendShapeCount = 36;
    79.         int blendShapeValue = value;
    80.         for (int blendShapeIndex = 0; blendShapeIndex < blendShapeCount; blendShapeIndex++)
    81.         {
    82.             targetSkinnedRenderer.SetBlendShapeWeight(blendShapeIndex, blendShapeValue);
    83.         }
    84.     }
    85.  
    86.     private float ValueConverter(float param)//Convert range(0 - 100) to range(-1 to +1)
    87.     {
    88.             param = param * 0.02f;
    89.             param = param + -1;
    90.             return param;
    91.     }
    92.  
    93.     // Update is called once per frame
    94.     void Update()
    95.     {
    96.         expressionPlayer.neckUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(0));
    97.         expressionPlayer.neckLeft_Right = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(1));
    98.         expressionPlayer.neckTiltLeft_Right = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(2));
    99.         expressionPlayer.headUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(3));
    100.         expressionPlayer.headLeft_Right = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(4));
    101.         expressionPlayer.headTiltLeft_Right = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(5));
    102.         expressionPlayer.jawOpen_Close = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(6));
    103.         expressionPlayer.jawForward_Back = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(7));
    104.         expressionPlayer.jawLeft_Right = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(8));
    105.         expressionPlayer.mouthLeft_Right = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(9));
    106.         expressionPlayer.mouthUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(10));
    107.         expressionPlayer.mouthNarrow_Pucker = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(11));
    108.         expressionPlayer.tongueOut = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(12));
    109.         expressionPlayer.tongueCurl = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(13));
    110.         expressionPlayer.tongueUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(14));
    111.         expressionPlayer.tongueLeft_Right = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(15));
    112.         expressionPlayer.tongueWide_Narrow = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(16));
    113.         expressionPlayer.leftMouthSmile_Frown = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(17));
    114.         expressionPlayer.rightMouthSmile_Frown = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(18));
    115.         expressionPlayer.leftLowerLipUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(19));
    116.         expressionPlayer.rightLowerLipUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(20));
    117.         expressionPlayer.leftUpperLipUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(21));
    118.         expressionPlayer.rightUpperLipUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(22));
    119.         expressionPlayer.leftCheekPuff_Squint = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(23));
    120.         expressionPlayer.rightCheekPuff_Squint = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(24));
    121.         expressionPlayer.noseSneer = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(25));
    122.         expressionPlayer.leftEyeOpen_Close = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(26));
    123.         expressionPlayer.rightEyeOpen_Close = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(27));
    124.         expressionPlayer.leftEyeUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(28));
    125.         expressionPlayer.rightEyeUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(29));
    126.         expressionPlayer.leftEyeIn_Out = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(30));
    127.         expressionPlayer.rightEyeIn_Out = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(31));
    128.         expressionPlayer.browsIn = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(32));
    129.         expressionPlayer.leftBrowUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(33));
    130.         expressionPlayer.rightBrowUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(34));
    131.         expressionPlayer.midBrowUp_Down = ValueConverter(targetSkinnedRenderer.GetBlendShapeWeight(35));
    132.     }
    133. }
    134.  
    Please feel free to optimize!
     
    LuLusg and hopeful like this.
  45. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    File.ReadAllText is expecting a file path. Assuming you've already instantiated outfit1, then you should just be able to pass outfit1.text to LoadFromRecipeString.

     
  46. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,203
    That's neat - I'll try to work it in as a "blend shape simulator". :)



     
    hopeful and Zante like this.
  47. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    Awesome : ] There's lots more to do however.

    The part it's falling down on at the moment is that most workflows using blendshapes occur inside the editor prior to being in runtime. As is, I don't know how to provide the same simulated shape data when not in play mode.

    The other problem is that, typically, blendshapes work in only positive ranges. That's to say rather than have a value for 'head tilt left/right' wherein -1 is right and +1 is left, we ought to treat it as two seperate blendshapes.

    So...
    • head tilt left 0 - 100
    • head tilt right 0 - 100
    The next step is for me, or someone else, to create additional blendshape parameters to reflect this and manage the ranges so that the two blendshapes above average out to singularly effect the expression player's head tilt left/right value. Either that or favour the larger value.

    To that end, we need to convert some more value ranges, so that -0.5 in the expression player equates +50 on the simulated blend shape. I can have a bit more of a play with it to see how far I get.

    Another example is the 'left eye open' blendshape needing to start at 0 (open) and end at 100 (closed), whereas currently the expression player handles it as -1 for closed and +1 for open.

    Edit: My partner has just done the maths, I have what I need to make these changes. Will try and post a new script in due course.
     
    Last edited: Sep 7, 2020
  48. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,676
    To work in edit mode, do you need something like blendshapes added to the bone builder?
     
  49. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    For edit mode, it needs a placeholder skinned mesh with the same blendshape values as those generated in the script.

    It's a bit unintuitive because, to see authentic results, the character needs to have been generated and the UMA Expression Player script running. The best workflow with the current setup would be one that works in runtime or to capture facial animation, using conventional means, and then (afterwards) change the blendshapes in the animation to match. I'm trying to make it a little bit easier to integrate with other workflows, admittedly selfishly, but facial mocap is still new to me and I have lots of silly questions and discoveries to make. It is unparalleled in its fidelity however.

    It might be possible, once I'm done with this, to extend the method to try and bake actual blendshapes into the mesh. If we get that far then UMA would have a true blendshape solution.
     
    Last edited: Sep 7, 2020
    hopeful likes this.
  50. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    Ok, here it is. My obsession wouldn't let me stop.

    The script below not only creates fake blendshapes but emulates them accurately. All values start at 0 and go to 100. This is in keeping with what Mixamo produces on its own assets. At this point, it should be possible to bake them to a mesh to be used outside of runtime. In the meantime however, we now have accurate runtime blendshape behaviours for all UMA-based characters.

    It needs optimisation but it is functional and accurate. Please test and let me know if anything is off!



    Code (CSharp):
    1. //    ============================================================
    2. //    Name:        UMABlendShapeExpressions
    3. //    Author:     Andrew Marunchak
    4. //    Copyright:    (c) 2020 Andrew Marunchak
    5. //  Thank you to Eli Curtz for creating the expression player
    6. //  script upon which this draws and maps its behaviours.
    7. //    ============================================================
    8.  
    9.  
    10. using System.Collections;
    11. using System.Collections.Generic;
    12. using UnityEngine;
    13. using UMA;
    14. using UMA.CharacterSystem;
    15. using UMA.PoseTools;
    16.  
    17. //When attached to the skinned mesh renderer object in UMA, this script creates dummy blendshapes and uses the values to control the expression player script
    18. //Use cases: When an UMA workflow requires blendshapes rather than bones to work
    19.  
    20. public class UMABlendShapeExpressions : MonoBehaviour
    21. {
    22.     public SkinnedMeshRenderer targetSkinnedRenderer;
    23.     public Mesh bakedMesh;
    24.     public UMAExpressionPlayer expressionPlayer;
    25.  
    26.     void Start()
    27.     {
    28.    
    29.         if(this.transform.parent.GetComponent<UMAExpressionPlayer>() == null)
    30.         {
    31.             Debug.Log("Please ensure an expression player has been added to the parent UMA GameObject - this script will now stop running");
    32.                 return;
    33.         }
    34.         else
    35.         {
    36.             expressionPlayer = this.transform.parent.GetComponent<UMAExpressionPlayer>();
    37.         }
    38.  
    39.         targetSkinnedRenderer = this.GetComponent<SkinnedMeshRenderer>(); //
    40.         bakedMesh = new Mesh();
    41.         Debug.Log("UMA skinned mesh found - now baking");
    42.         targetSkinnedRenderer.BakeMesh(bakedMesh);
    43.  
    44.         Vector3[] junkData = new Vector3[bakedMesh.vertices.Length];
    45.  
    46.  
    47.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Eyes Left", 100, junkData, junkData, junkData);
    48.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Eyes Right", 100, junkData, junkData, junkData);
    49.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Eyes Up", 100, junkData, junkData, junkData);
    50.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Eyes Down", 100, junkData, junkData, junkData);
    51.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Eyelid", 100, junkData, junkData, junkData);
    52.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Eyelid", 100, junkData, junkData, junkData);
    53.  
    54.  
    55.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Neck Left", 100, junkData, junkData, junkData);
    56.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Neck Right", 100, junkData, junkData, junkData);
    57.  
    58.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Neck Up", 100, junkData, junkData, junkData);
    59.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Neck Down", 100, junkData, junkData, junkData);
    60.  
    61.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Neck Tilt Left", 100, junkData, junkData, junkData);
    62.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Neck Tilt Right", 100, junkData, junkData, junkData);
    63.  
    64.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Head Left", 100, junkData, junkData, junkData);
    65.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Head Right", 100, junkData, junkData, junkData);
    66.  
    67.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Head Up", 100, junkData, junkData, junkData);
    68.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Head Down", 100, junkData, junkData, junkData);
    69.  
    70.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Head Tilt Left", 100, junkData, junkData, junkData);
    71.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Head Tilt Right", 100, junkData, junkData, junkData);
    72.  
    73.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Smile Left", 100, junkData, junkData, junkData);
    74.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Smile Right", 100, junkData, junkData, junkData);
    75.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Frown Left", 100, junkData, junkData, junkData);
    76.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Frown Right", 100, junkData, junkData, junkData);
    77.  
    78.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Jaw Open", 100, junkData, junkData, junkData);
    79.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Jaw Forward", 100, junkData, junkData, junkData);
    80.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Jaw Left", 100, junkData, junkData, junkData);
    81.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Jaw Right", 100, junkData, junkData, junkData);
    82.  
    83.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mouth Up", 100, junkData, junkData, junkData);
    84.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mouth Down", 100, junkData, junkData, junkData);
    85.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mouth Left", 100, junkData, junkData, junkData);
    86.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mouth Right", 100, junkData, junkData, junkData);
    87.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mouth Narrow", 100, junkData, junkData, junkData);
    88.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mouth Pucker", 100, junkData, junkData, junkData);
    89.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Tongue Up", 100, junkData, junkData, junkData);
    90.  
    91.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Lower Lip Up", 100, junkData, junkData, junkData);
    92.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Lower Lip Down", 100, junkData, junkData, junkData);
    93.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Lower Lip Up", 100, junkData, junkData, junkData);
    94.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Lower Lip Down", 100, junkData, junkData, junkData);
    95.  
    96.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Upper Lip Up", 100, junkData, junkData, junkData);
    97.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Upper Lip Down", 100, junkData, junkData, junkData);
    98.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Upper Lip Up", 100, junkData, junkData, junkData);
    99.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Upper Lip Down", 100, junkData, junkData, junkData);
    100.  
    101.    
    102.  
    103.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Cheek Out", 100, junkData, junkData, junkData);
    104.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Cheek Squint", 100, junkData, junkData, junkData);
    105.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Cheek Out", 100, junkData, junkData, junkData);
    106.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Cheek Squint", 100, junkData, junkData, junkData);
    107.  
    108.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Nose Sneer", 100, junkData, junkData, junkData);
    109.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Brows In", 100, junkData, junkData, junkData);
    110.    
    111.  
    112.    
    113.    
    114.  
    115.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Brow Up", 100, junkData, junkData, junkData);
    116.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Right Brow Down", 100, junkData, junkData, junkData);
    117.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Brow Up", 100, junkData, junkData, junkData);
    118.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Left Brow Down", 100, junkData, junkData, junkData);
    119.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mid Brow Up", 100, junkData, junkData, junkData);
    120.         targetSkinnedRenderer.sharedMesh.AddBlendShapeFrame("UMA Player Mid Brow Down", 100, junkData, junkData, junkData);
    121.         //Mesh.GetBlendShapeFrameVertices.del;
    122.         //ResetUMABlendShapes(50);//the value to set the blendshapes to
    123.     }
    124.  
    125.     public void ResetUMABlendShapes(int value)
    126.     {
    127.         int blendShapeCount = 36;
    128.         int blendShapeValue = value;
    129.         for (int blendShapeIndex = 0; blendShapeIndex < blendShapeCount; blendShapeIndex++)
    130.         {
    131.             targetSkinnedRenderer.SetBlendShapeWeight(blendShapeIndex, blendShapeValue);
    132.         }
    133.     }
    134.  
    135.     private float ValueConverter(float param)//Convert range(0 - 100) to range(-1 to +1)
    136.     {
    137.             param = param * 0.02f;
    138.             param = param + -1;
    139.             return param;
    140.     }
    141.  
    142.     // Update is called once per frame
    143.     void Update()
    144.     {
    145.         //BLENDSHAPE EMULATION START//
    146.  
    147.         //EYE GROUPS
    148.         float eyesLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Eyes Left"));
    149.         float eyesRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Eyes Right"));
    150.         if (eyesLeft >= eyesRight)
    151.         {
    152.             expressionPlayer.leftEyeIn_Out = ValueConverter3(eyesRight - eyesLeft);
    153.             expressionPlayer.rightEyeIn_Out = ValueConverter3(eyesLeft - eyesRight);
    154.         }
    155.         if (eyesLeft < eyesRight)
    156.         {
    157.             expressionPlayer.leftEyeIn_Out = ValueConverter4(eyesLeft - eyesRight);
    158.             expressionPlayer.rightEyeIn_Out = ValueConverter4(eyesRight - eyesLeft);
    159.         }
    160.  
    161.         float eyesUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Eyes Up"));
    162.         float eyesDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Eyes Down"));
    163.         if (eyesUp >= eyesDown)
    164.         {
    165.             expressionPlayer.leftEyeUp_Down = ValueConverter3(eyesUp - eyesDown);
    166.             expressionPlayer.rightEyeUp_Down = ValueConverter3(eyesUp - eyesDown);
    167.         }
    168.         if (eyesUp < eyesDown)
    169.         {
    170.             expressionPlayer.leftEyeUp_Down = ValueConverter4(eyesDown - eyesUp);
    171.             expressionPlayer.rightEyeUp_Down = ValueConverter4(eyesDown - eyesUp);
    172.         }
    173.  
    174.  
    175.  
    176.         //TONGUE
    177.         float tongueUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Tongue Up"));
    178.         expressionPlayer.tongueUp_Down = ValueConverter3(tongueUp);
    179.  
    180.         //JAW
    181.         float jawForward = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Jaw Forward"));
    182.         expressionPlayer.jawForward_Back = ValueConverter3(jawForward);
    183.  
    184.         float jawLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Jaw Left"));
    185.         float jawRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Jaw Right"));
    186.         if (jawLeft >= jawRight) { expressionPlayer.jawLeft_Right = ValueConverter3(jawLeft - jawRight); }
    187.         if (jawLeft < jawRight) { expressionPlayer.jawLeft_Right = ValueConverter4(jawRight - jawLeft); }
    188.  
    189.         float jawOpen = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Jaw Open"));
    190.         expressionPlayer.jawOpen_Close = ValueConverter3(jawOpen);
    191.  
    192.  
    193.         //MOUTH
    194.         float mouthNarrow = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mouth Narrow"));
    195.         float mouthPucker = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mouth Pucker"));
    196.         if (mouthNarrow >= mouthPucker) { expressionPlayer.mouthNarrow_Pucker = ValueConverter3(mouthPucker - mouthNarrow); }
    197.         if (mouthNarrow < mouthPucker) { expressionPlayer.mouthNarrow_Pucker = ValueConverter4(mouthNarrow - mouthPucker); }
    198.  
    199.         float mouthDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mouth Down"));
    200.         float mouthUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mouth Up"));
    201.         if (mouthDown >= mouthUp) { expressionPlayer.mouthUp_Down = ValueConverter3(mouthUp - mouthDown); }
    202.         if (mouthDown < mouthUp) { expressionPlayer.mouthUp_Down = ValueConverter4(mouthDown - mouthUp); }
    203.  
    204.         float mouthLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mouth Left"));
    205.         float mouthRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mouth Right"));
    206.         if (mouthLeft >= mouthRight) { expressionPlayer.mouthLeft_Right = ValueConverter3(mouthLeft - mouthRight); }
    207.         if (mouthLeft < mouthRight) { expressionPlayer.mouthLeft_Right = ValueConverter4(mouthRight - mouthLeft); }
    208.  
    209.  
    210.         //SMILE/FROWN
    211.  
    212.         float smileLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Smile Left"));
    213.         float frownLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Frown Left"));
    214.         if (smileLeft >= frownLeft) { expressionPlayer.leftMouthSmile_Frown = ValueConverter3(smileLeft - frownLeft); }
    215.         if (smileLeft < frownLeft) { expressionPlayer.leftMouthSmile_Frown = ValueConverter4(frownLeft - smileLeft); }
    216.  
    217.         float smileRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Smile Right"));
    218.         float frownRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Frown Right"));
    219.         if (smileRight >= frownRight) { expressionPlayer.rightMouthSmile_Frown = ValueConverter3(smileRight - frownRight); }
    220.         if (smileRight < frownRight) { expressionPlayer.rightMouthSmile_Frown = ValueConverter4(frownRight - smileRight); }
    221.  
    222.  
    223.         //LIPS
    224.         float leftLowerLipUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Lower Lip Up"));
    225.         float leftLowerLipDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Lower Lip Down"));
    226.         if (leftLowerLipUp >= leftLowerLipDown) { expressionPlayer.leftLowerLipUp_Down = ValueConverter3(leftLowerLipUp - leftLowerLipDown); }
    227.         if (leftLowerLipUp < leftLowerLipDown) { expressionPlayer.leftLowerLipUp_Down = ValueConverter4(leftLowerLipDown - leftLowerLipUp); }
    228.  
    229.         float rightLowerLipUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Lower Lip Up"));
    230.         float rightLowerLipDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Lower Lip Down"));
    231.         if (rightLowerLipUp >= rightLowerLipDown) { expressionPlayer.rightLowerLipUp_Down = ValueConverter3(rightLowerLipUp - rightLowerLipDown); }
    232.         if (rightLowerLipUp < rightLowerLipDown) { expressionPlayer.rightLowerLipUp_Down = ValueConverter4(rightLowerLipDown - rightLowerLipUp); }
    233.  
    234.  
    235.         float leftUpperLipUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Upper Lip Up"));
    236.         float leftUpperLipDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Upper Lip Down"));
    237.         if (leftUpperLipUp >= leftUpperLipDown) { expressionPlayer.leftUpperLipUp_Down = ValueConverter3(leftUpperLipUp - leftUpperLipDown); }
    238.         if (leftUpperLipUp < leftUpperLipDown) { expressionPlayer.leftUpperLipUp_Down = ValueConverter4(leftUpperLipDown - leftUpperLipUp); }
    239.  
    240.         float rightUpperLipUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Upper Lip Up"));
    241.         float rightUpperLipDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Upper Lip Down"));
    242.         if (rightUpperLipUp >= rightUpperLipDown) { expressionPlayer.rightUpperLipUp_Down = ValueConverter3(rightUpperLipUp - rightUpperLipDown); }
    243.         if (rightUpperLipUp < rightUpperLipDown) { expressionPlayer.rightUpperLipUp_Down = ValueConverter4(rightUpperLipDown - rightUpperLipUp); }
    244.  
    245.  
    246.    
    247.  
    248.         //Cheek & Squint (the squint in this case negates the cheek out) - this is the way the expression player is mapped
    249.         float leftCheekOut = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Cheek Out"));
    250.         float leftCheekSquint = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Cheek Squint"));
    251.         if (leftCheekOut >= leftCheekSquint) { expressionPlayer.leftCheekPuff_Squint = ValueConverter3(leftCheekOut - leftCheekSquint); }
    252.         if (leftCheekOut < leftCheekSquint) { expressionPlayer.leftCheekPuff_Squint = ValueConverter4(leftCheekSquint - leftCheekOut); }
    253.  
    254.         float rightCheekOut = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Cheek Out"));
    255.         float rightCheekSquint = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Cheek Squint"));
    256.         if (rightCheekOut >= rightCheekSquint) { expressionPlayer.rightCheekPuff_Squint = ValueConverter3(rightCheekOut - rightCheekSquint); }
    257.         if (rightCheekOut < rightCheekSquint) { expressionPlayer.rightCheekPuff_Squint = ValueConverter4(rightCheekSquint - rightCheekOut); }
    258.  
    259.         //NOSE
    260.         float noseSneer = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Nose Sneer"));
    261.         expressionPlayer.noseSneer = ValueConverter3(noseSneer);
    262.  
    263.         //BROWS (up/down & left/right values shared and averaged to UMA ExpressionPlayer ...BrowUp_Down &BrowLeft_Right
    264.         float leftBrowUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Brow Up"));
    265.         float leftBrowDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Brow Down"));
    266.         if (leftBrowUp >= leftBrowDown) { expressionPlayer.leftBrowUp_Down = ValueConverter3(leftBrowUp - leftBrowDown); }
    267.         if (leftBrowUp < leftBrowDown) { expressionPlayer.leftBrowUp_Down = ValueConverter4(leftBrowDown - leftBrowUp); }
    268.  
    269.         float rightBrowUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Brow Up"));
    270.         float rightBrowDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Brow Down"));
    271.         if (rightBrowUp >= rightBrowDown) { expressionPlayer.rightBrowUp_Down = ValueConverter3(rightBrowUp - rightBrowDown); }
    272.         if (rightBrowUp < rightBrowDown) { expressionPlayer.rightBrowUp_Down = ValueConverter4(rightBrowDown - rightBrowUp); }
    273.  
    274.         float midBrowUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mid Brow Up"));
    275.         float midBrowDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Mid Brow Down"));
    276.         if (midBrowUp >= midBrowDown) { expressionPlayer.midBrowUp_Down = ValueConverter3(midBrowUp - midBrowDown); }
    277.         if (midBrowUp < midBrowDown) { expressionPlayer.midBrowUp_Down = ValueConverter4(midBrowDown - midBrowUp); }
    278.  
    279.         float browsIn = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Brows In"));
    280.         expressionPlayer.browsIn = ValueConverter3(browsIn);
    281.    
    282.  
    283.  
    284.         //EYELIDS (0 is open, 100 is closed)
    285.         float eyelidLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Left Eyelid"));
    286.         expressionPlayer.leftEyeOpen_Close = ValueConverter4(eyelidLeft);
    287.         float eyelidRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Right Eyelid"));
    288.         expressionPlayer.rightEyeOpen_Close = ValueConverter4(eyelidRight);
    289.  
    290.  
    291.         //NECK left/right/up/down and tilt (values shared and averaged to UMA ExpressionPlayer neckTiltLeft_Right etc...
    292.  
    293.         float neckLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Neck Left"));
    294.         float neckRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Neck Right"));
    295.         if (neckLeft >= neckRight) { expressionPlayer.neckLeft_Right = ValueConverter3(neckLeft - neckRight); }
    296.         if (neckLeft < neckRight) { expressionPlayer.neckLeft_Right = ValueConverter4(neckRight - neckLeft); }
    297.  
    298.         float neckUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Neck Up"));
    299.         float neckDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Neck Down"));
    300.         if (neckUp >= neckDown) { expressionPlayer.neckUp_Down = ValueConverter3(neckUp - neckDown); }
    301.         if (neckUp < neckDown) { expressionPlayer.neckUp_Down = ValueConverter4(neckDown - neckUp); }
    302.  
    303.         float neckTiltLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Neck Tilt Left"));
    304.         float neckTiltRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Neck Tilt Right"));
    305.         if (neckTiltLeft >= neckTiltRight) { expressionPlayer.neckTiltLeft_Right = ValueConverter3(neckTiltLeft - neckTiltRight); }
    306.         if (neckTiltLeft < neckTiltRight) { expressionPlayer.neckTiltLeft_Right = ValueConverter4(neckTiltRight - neckTiltLeft); }
    307.  
    308.  
    309.  
    310.         //HEAD left/right/up/down and tilt (values shared and averaged to UMA ExpressionPlayer headTiltLeft_Right etc...
    311.  
    312.         float headLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Head Left"));
    313.         float headRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Head Right"));
    314.         if (headLeft >= headRight) { expressionPlayer.headLeft_Right = ValueConverter3(headLeft - headRight); }
    315.         if (headLeft < headRight) { expressionPlayer.headLeft_Right = ValueConverter4(headRight - headLeft); }
    316.  
    317.         float headUp = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Head Up"));
    318.         float headDown = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Head Down"));
    319.         if (headUp >= headDown) { expressionPlayer.headUp_Down = ValueConverter3(headUp - headDown); }
    320.         if (headUp < headDown) { expressionPlayer.headUp_Down = ValueConverter4(headDown - headUp); }
    321.  
    322.         float headTiltLeft = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Head Tilt Left"));
    323.         float headTiltRight = targetSkinnedRenderer.GetBlendShapeWeight(BlendShapeByString("UMA Player Head Tilt Right"));
    324.         if (headTiltLeft >= headTiltRight) { expressionPlayer.headTiltLeft_Right = ValueConverter3(headTiltLeft - headTiltRight); }
    325.         if (headTiltLeft < headTiltRight) { expressionPlayer.headTiltLeft_Right = ValueConverter4(headTiltRight - headTiltLeft); }
    326.  
    327.         //BLENDSHAPE EMULATION END//
    328.     }
    329.  
    330.     public int BlendShapeByString(string arg)
    331.     {
    332.         int blendIndex;
    333.         int blendShapeLength;
    334.         blendShapeLength = targetSkinnedRenderer.sharedMesh.blendShapeCount;
    335.         for (int i = 0; i < blendShapeLength; i++)
    336.         {
    337.             if(targetSkinnedRenderer.sharedMesh.GetBlendShapeName(i) == arg)
    338.             {
    339.                 return i;
    340.             }
    341.         }
    342.         return -1;
    343.     }
    344.  
    345.  
    346.  
    347.     private float ValueConverter2(float param)//Convert range(0 - 100) to range(-1 to +1) [0 is eyes open, 100 is now eyes closed]
    348.     {
    349.         param = -param;
    350.         param = param * 0.02f;
    351.         param = param + 1f;
    352.         return param;
    353.     }
    354.  
    355.     private float ValueConverter3(float param)//Convert range(0 - 100) to range(-1 to +1) [0 to 100 left]
    356.     {
    357.         param = param * 0.01f;
    358.         return param;
    359.     }
    360.  
    361.     private float ValueConverter4(float param)//Convert range(0 - 100) to range(-1 to +1) [0 to 100 right]
    362.     {
    363.         param = -param;
    364.         param = param * 0.01f;
    365.         //param = param + 1f;
    366.         return param;
    367.     }
    368.  
    369. }
    370.  
     
    Last edited: Sep 8, 2020
    LuLusg, dmenefee, Jaimi and 1 other person like this.