Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

UMA Character System (deprecated)

Discussion in 'Assets and Asset Store' started by Jaimi, Dec 1, 2015.

  1. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,628
    I'm not sure you can go flatter than the base UMA model, unfortunately.

    In the original UMA, before release, both male and female were made from the same single model, and there was a slider to switch from "more male" to "more female," which was basically just a boob slider. It would have been helpful to have retained that in some manner, I think, and I've brought it up before, but I suspect Fernando has been too busy to dig it up out of his archives (if he even still has any of it) and add it to github.

    That said, the torso is just a slot. Maybe the male torso can be repurposed as a smaller chested female torso ...? Or a new female torso slot created that has a smaller chest.
     
    twobob likes this.
  2. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,929
    That is a good idea. Actually, the male would work to some extent and just changing out the female head, but not sure that would work either. Might have seam problems.
     
    Vinchinderlous likes this.
  3. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,628
    If you go to the female base UMA and simply reduce the chest, that would avoid seams issues. Overlays will still work with that, but any slots you plug in - unless they were created by you - will be for the fuller-chested model.
     
  4. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    Yes, actually there is! Take a look at the RaceData - in this case it is named "Human Female" under "UMA/CONTENT/UMA/HUMANOID/RACES" - this specifies the DNA Ranges asset, and the DNA Converter Behavior. You can adjust the ranges in the "Human Female UMADNAHumanoid Ranges" asset, and you can even adjust how the DNA values are applied in the HumanFemaleDNAConverterBehavior class.

    Have fun!
     
  5. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,628
    Will this reduce the bust below where the base female UMA is set at?
     
  6. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    It will - there are actually two bones per breast - the outer and inner bones.

    This data in the converter is where it actually changes and clamps the bone values (the inner bones are children of the outer bones, so they are being scaled also)

    Code (csharp):
    1.  
    2.    skeleton.SetScale(leftOuterBreastHash,
    3. new Vector3(
    4. Mathf.Clamp(1 + (umaDna.breastSize - 0.5f) * 1.50f + (umaDna.upperWeight - 0.5f) * 0.10f, 0.6f, 1.5f),
    5. Mathf.Clamp(1 + (umaDna.breastSize - 0.5f) * 1.50f + (umaDna.upperWeight - 0.5f) * 0.10f, 0.6f, 1.5f),
    6. Mathf.Clamp(1 + (umaDna.breastSize - 0.5f) * 1.50f + (umaDna.upperWeight - 0.5f) * 0.10f, 0.6f, 1.5f)));
    7. skeleton.SetScale(rightOuterBreastHash,
    8. new Vector3(
    9. Mathf.Clamp(1 + (umaDna.breastSize - 0.5f) * 1.50f + (umaDna.upperWeight - 0.5f) * 0.10f, 0.6f, 1.5f),
    10. Mathf.Clamp(1 + (umaDna.breastSize - 0.5f) * 1.50f + (umaDna.upperWeight - 0.5f) * 0.10f, 0.6f, 1.5f),
    11. Mathf.Clamp(1 + (umaDna.breastSize - 0.5f) * 1.50f + (umaDna.upperWeight - 0.5f) * 0.10f, 0.6f, 1.5f)));
    12.  
    To see what effect changing the ranges has (without modifying the clamp above). you can simply go to the two bones mentioned above (the RightOuterBreast and LeftOuterBreast) after you have generated the avatar and lower the scaling while it's running. It will scale pretty well.
     
    BackwoodsGaming likes this.
  7. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,628
    Well then ... far out! :)
     
  8. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,929
    Thanks, Jaimi! I will try that out. :)
     
  9. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    No problem. Just moving the bones in the editor won't affect the vertex normals, though. Not sure if UMA recalculates those itself.
     
  10. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,929
    I am having problems with the eye color slider. It doesn't seem to be changing the color. I checked to make sure it was set right in the recipes and it seems to be.
     
    Vinchinderlous likes this.
  11. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    Hi Teila -

    On your base recipe, do you have a shared color on the EyeOverlayAdjust?

    Screen Shot 2015-12-13 at 6.24.34 PM.png

    If so, then it will colorize after calling SetColor(string Name,Color c ,bool UpdateTexture=true).

    If it's not working, then I would:

    1. Check the case of the color name -- it's case sensitive (sorry)
    2. Make sure that EyeOverlayAdjust is not added in twice or in a different recipe (without the shared color). I did this once, actually.
    3. Have you resized the texture? If so, you have to delete the overlay from the editor and re-add it. (UMA issue -- it remembers the size when it's first added). I did this once also.

    Hope this helps,

    Jaimi
     
  12. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,929
    Thanks.
    I haven't touched the textures or the color names you put in so probably not that. I will make sure all the recipes are correct, although I think I only added one recipe so far. :) I started a new project. I had some weird errors that I don't think had anything to do with UMA in my other project.
     
    Vinchinderlous likes this.
  13. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    I looked back at the default recipes, and the eyes are not properly defined in the base recipes - Sorry! You'll need to set them up like I showed above. I'll fix this in the next version I upload.

    Currently there are no code changes, except to the sample application, and a couple of changes to the recipes.
     
    Teila and hopeful like this.
  14. Teila

    Teila

    Joined:
    Jan 13, 2013
    Posts:
    6,929
    No problem! Thanks for the heads up. :)
     
    Vinchinderlous likes this.
  15. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,300
    Hello Jaimi,

    thanks for the link. I added UMA 2 PBR then the UMA rpg starter package.

    When I try to run the test Scene it works (naked woman).

    When I add an "UMA Receipe" to the Avatar in the Scene, it gives me null exceptions like this one:

    NullReferenceException: Object reference not set to an instance of an object
    UMACharacterSystem.CharacterAvatar.UpdateColors () (at Assets/UMA/Extensions/CharacterSystem/CharacterAvatar.cs:188)
    UMACharacterSystem.CharacterAvatar.Load (.UMARecipeBase umaRecipe, .UMARecipeBase[] umaAdditionalRecipes) (at Assets/UMA/Extensions/CharacterSystem/CharacterAvatar.cs:230)
    UMACharacterSystem.CharacterAvatar.BuildCharacter (Boolean RestoreDNA) (at Assets/UMA/Extensions/CharacterSystem/CharacterAvatar.cs:163)
    UMACharacterSystem.CharacterAvatar.Start () (at Assets/UMA/Extensions/CharacterSystem/CharacterAvatar.cs:46)

    Is this additional functionality to UMA 2 in General? Will it later be added to UMA 2? Or is it just to create receipes?

    I am working on a rpg / randominzed sandbox game. If I spawn an NPC in my world, I want to randomly generate some mixed armor and weapons or mixed clothes on it...

    I own the rpg starter kit and we are working on some own additional weapons and tools and helmets :)

    Maybe we'll make a free package with those when we got our UMA stuff working, thanks :)
     
  16. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    Hi - I added a bunch of changes to UMA to enhance creating recipes in the recipe editor, this is why it needs the updated UMA I have in the project. These changes are already in the 2.0 UMA on GitHub, but since they haven't updated the asset store version yet, you'll need to use the version from github (or the one I included in the download).

    The main functionality is the ability to define multi-slot, multi-overlay pieces of equipment, and swap them out on the fly. With the ability to hide "hidden" parts of the model so you don't get z-fighting (and it's cheaper to render).

    It would be really easy to do exactly what you are wanting to do with the system - randomly generating armor and or DNA. The only thing you need to do is predefine all the individual pieces of equipment, and then at runtime you can randomly assign them to the slots.

    This code randomly generates a female shirt (assuming you have created the recipes for it):

    Code (csharp):
    1.  
    2. int shirtNumber = Random.Range(0,CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Chest].Count-1);
    3. UMATextRecipe tr = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Chest][shirtNumber];
    4.  
    The errors you have above sound like you haven't added the slots and overlays to their libraries - can you validate that?

    Also, it shouldn't be generating a nude female, she should be wearing a denim bikini. Be sure you have the latest update here:

    http://www.aztica.com/images/umacharactersystem.zip
     
    Last edited: Dec 14, 2015
    theANMATOR2b likes this.
  17. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    I'm loading the MaleBase but when I move the shirt or pants slider it adds the female clothing to the male. These values seem to be hardcoded,

    ShirtSlider.maxValue = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Chest].Count - 1;
    PantsSlider.maxValue = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Legs].Count - 1;

    Should I change these?

    What do I need to change to use the Male?
     
    Last edited: Jan 3, 2016
  18. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    Yes - sorry, that is just sample code to show how the system works. I'm putting together a more comprehensive customizer (that will be based on the wardrobe slots you define and the sex), but it isn't ready yet. But you have the right idea, you need to set the sex on your avatar, set the correct sex base model, and pull the recipes from the correct sex.
     
  19. AGregori

    AGregori

    Joined:
    Dec 11, 2014
    Posts:
    526
    Jaimi, you're a lifesaver with this system.
    Please keep updating it and make it non-free, I'll pay anything for it. =)
     
    BackwoodsGaming and Teila like this.
  20. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    Ah thanks Jaimi, I almost have it but I can't find where to set the recipes for the base mode. Where should I look?
     
  21. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    It's on the "CharacterAvatar" script - the base recipe is in the "Uma Recipe" field. If you want to load/save the avatar from an XML file, you'll also need to set the "Male Base"/"Female Base"/"UnisexBase" fields, because the avatar will call the "SetSex" function which needs these set (it simply loads them into UMARecipe).
     
    Last edited: Jan 3, 2016
    hopeful likes this.
  22. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    You're welcome!
     
  23. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    for anyone wanting gender switching I got it working by making a few small changes to the TestCustomization script:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4. using UMACharacterSystem;
    5.  
    6. public class TestCustomizer : MonoBehaviour {
    7.     public string gender = "male";
    8.    public CharacterAvatar Avatar;
    9.    public SharedColorTable Eyes;
    10.    public SharedColorTable Hair;
    11.    public SharedColorTable Skin;
    12.  
    13.    public Slider HairSlider;
    14.    public Slider ShirtSlider;
    15.    public Slider PantsSlider;
    16.  
    17.    public MouseOrbitImproved Orbitor;
    18.  
    19.    /// <summary>
    20.    /// Initialize the sliders with the max values
    21.    /// </summary>
    22.    public void Start()
    23.    {
    24.         gender = Avatar.Sex.ToString();
    25.         if (gender=="Female")
    26.         {
    27.             Avatar.umaRecipe = Avatar.FemaleBase;
    28.             Avatar.enabled = true;
    29.             HairSlider.maxValue = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Hair].Count - 1;
    30.             ShirtSlider.maxValue = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Chest].Count - 1;
    31.             PantsSlider.maxValue = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Legs].Count - 1;
    32.         }else if (gender=="Male")
    33.         {
    34.             Avatar.umaRecipe = Avatar.MaleBase;
    35.             Avatar.enabled = true;
    36.  
    37.             HairSlider.maxValue = CharacterSystem.Recipes[Sex.Male][WardrobeSlot.Hair].Count - 1;
    38.             ShirtSlider.maxValue = CharacterSystem.Recipes[Sex.Male][WardrobeSlot.Chest].Count - 1;
    39.             PantsSlider.maxValue = CharacterSystem.Recipes[Sex.Male][WardrobeSlot.Legs].Count - 1;
    40.         }
    41.    }
    42.  
    43.    /// <summary>
    44.    /// Sets the hair. If a negative value is passed, then the slot is cleared.
    45.    /// </summary>
    46.    /// <param name="col">Col.</param>
    47.    public void SetHair(float HairNumber)
    48.    {
    49.       int hairNumber = (int)HairNumber;
    50.         if (gender == "Female")
    51.         {
    52.             if (hairNumber >= 0)
    53.             {
    54.                 UMATextRecipe tr = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Hair][hairNumber];
    55.                 Avatar.SetSlot(tr);
    56.             }
    57.             else
    58.             {
    59.                 Avatar.ClearSlot(WardrobeSlot.Hair);
    60.             }
    61.         }
    62.         if (gender == "Male")
    63.         {
    64.             if (hairNumber >= 0)
    65.             {
    66.                 UMATextRecipe tr = CharacterSystem.Recipes[Sex.Male][WardrobeSlot.Hair][hairNumber];
    67.                 Avatar.SetSlot(tr);
    68.             }
    69.             else
    70.             {
    71.                 Avatar.ClearSlot(WardrobeSlot.Hair);
    72.             }
    73.         }
    74.         Avatar.BuildCharacter(true);
    75.    }
    76.  
    77.    /// <summary>
    78.    /// Sets the shirt. If a negative value is passed, then the slot is cleared.
    79.    /// </summary>
    80.    /// <param name="col">Col.</param>
    81.    public void SetShirt(float ShirtNumber)
    82.    {
    83.       int shirtNumber = (int)ShirtNumber;
    84.         if (gender == "Female")
    85.         {
    86.             if (shirtNumber >= 0)
    87.             {
    88.                 UMATextRecipe tr = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Chest][shirtNumber];
    89.                 Avatar.SetSlot(tr);
    90.             }
    91.             else
    92.             {
    93.                 Avatar.ClearSlot(WardrobeSlot.Chest);
    94.             }
    95.         }
    96.         if (gender == "Male") {
    97.             if (shirtNumber >= 0)
    98.             {
    99.                 UMATextRecipe tr = CharacterSystem.Recipes[Sex.Male][WardrobeSlot.Chest][shirtNumber];
    100.                 Avatar.SetSlot(tr);
    101.             }
    102.             else
    103.             {
    104.                 Avatar.ClearSlot(WardrobeSlot.Chest);
    105.             }
    106.         }
    107.         Avatar.BuildCharacter(true);
    108.    }
    109.  
    110.    /// <summary>
    111.    /// Sets the pants. If a negative value is passed, then the slot is cleared.
    112.    /// </summary>
    113.    /// <param name="col">Col.</param>
    114.    public void SetPants(float PantsNumber)
    115.    {
    116.       int pantsNumber = (int)PantsNumber;
    117.         if (gender == "Female")
    118.         {
    119.             if (pantsNumber >= 0)
    120.             {
    121.                 UMATextRecipe tr = CharacterSystem.Recipes[Sex.Female][WardrobeSlot.Legs][pantsNumber];
    122.                 Avatar.SetSlot(tr);
    123.             }
    124.             else
    125.             {
    126.                 Avatar.ClearSlot(WardrobeSlot.Legs);
    127.             }
    128.         }
    129.         if (gender == "Male")
    130.         {
    131.             if (pantsNumber >= 0)
    132.             {
    133.                 UMATextRecipe tr = CharacterSystem.Recipes[Sex.Male][WardrobeSlot.Legs][pantsNumber];
    134.                 Avatar.SetSlot(tr);
    135.             }
    136.             else
    137.             {
    138.                 Avatar.ClearSlot(WardrobeSlot.Legs);
    139.             }
    140.         }
    141.         Avatar.BuildCharacter(true);
    142.    }
    143.  
    144.    /// <summary>
    145.    /// Point the mouse orbitor at the body center
    146.    /// </summary>
    147.    public void TargetBody()
    148.    {
    149.       Orbitor.distance = 1.4f;
    150.       Orbitor.TargetBone = "Root/Global/Position/Hips/LowerBack";
    151.    }
    152.  
    153.    /// <summary>
    154.    /// Point the mouse orbitor at the neck, so you can see the face.
    155.    /// </summary>
    156.    public void TargetFace()
    157.    {
    158.       Orbitor.distance = 0.4f;
    159.       Orbitor.TargetBone = "Root/Global/Position/Hips/LowerBack/Spine/Spine1/Neck/Head";
    160.    }
    161.  
    162.  
    163.    /// <summary>
    164.    /// This is a sample UI function to set eye color.
    165.    /// </summary>
    166.    /// <param name="Col">Col.</param>
    167.    public void SetEyeColor(float fCol)
    168.    {
    169.       int Col = (int)fCol;
    170.       Avatar.SetColor("Eyes",Eyes.colors[Col].color);
    171.    }
    172.  
    173.    /// <summary>
    174.    /// This is a sample UI function to set the skin color.
    175.    /// The texture is rebuilt.
    176.    /// </summary>
    177.    /// <param name="Col">fCol.</param>
    178.    public void SetSkinColor(float fCol)
    179.    {
    180.       int Col = (int)fCol;
    181.       Avatar.SetColor ("Skin", Skin.colors[Col].color);
    182.    }
    183.  
    184.    /// <summary>
    185.    /// This is a sample UI function to set the hair color.
    186.    /// </summary>
    187.    /// <param name="Col">Col.</param>
    188.    public void SetHairColor(float Col)
    189.    {
    190.       int col = (int)Col;
    191.       Avatar.SetColor("Hair",Hair.colors[col].color);
    192.    }
    193. }
    194.  
    Jaimi how would I add a male hair style that uses an overlay only, no slot?
     
    Teila likes this.
  24. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    What you do is create a new recipe like normal, and add the head slot (same one you used on the base recipe), and add the overlay to that. It won't add the head twice (it gets cleaned up in the merge) -- the overlay will be applied to the first head slot.

    The building goes something like this:

    The base recipe is added.

    Then, it will loop through the wardrobe in WardrobeSlot (enum) order.
    It will add everything to the new recipe (unless it's supressed).

    If a slot is already there, it is discarded, and overlays are added to the original.
    Once the recipes are added, it will go through and drop out any UMA slots that are hidden.

    Then it updates all the colors, and rebuilds the model.
     
    Teila and hopeful like this.
  25. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    Wonderful. Think I have everything figured out now, have male female switching and all wardrove slots working. Thanks for this great and easy system!
     
  26. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    You're welcome - have fun!
     
  27. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    I added a wardrobe slot called BodyOverlay then created male and female recipes with the head, torso, hands, legs, feet slots and a new Body overlay (FemaleBody02, FemaleHead02) and created a slider to change them in the editor but when I do the body overlay texture changes but so do the other overlays too (The female pants overlay, eyebrows etc) Is there a way to only change the body overlay without changing everything else too?
     
  28. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    It applies wardrobe slots in numeric order, so a bodyoverlay would need to be before the eyebrows/pants etc in the enum.

    Edit: I created the wardrobe slots before Will added the body variants, so I didn't add a body texture to the initial wardrobe definition. It's all completely data driven, so you can tune the WardrobeSlot enum anyway you want. Because the enum is converted to an int internally (it's part of Unity's serialization), changing the enum after you have created a bunch of recipes means you might have to adjust your recipes.

    To address this, I modified the current one to look like this (so there is empty space for people to add slots before others without causing them to have to go through their recipes and reassign the Wardrobe Slot:

    Code (CSharp):
    1.     public enum WardrobeSlot
    2.     {
    3.         None=0,
    4.         Body=5,
    5.         Face=10,
    6.         Complexion=20,
    7.         Hair=30,
    8.         Eyebrows=40,
    9.         Beard=50,
    10.         Ears=60,
    11.         Helmet=70,
    12.         Shoulders=80,
    13.         Chest=90,
    14.         Arms=100,
    15.         Hands=110,
    16.         Waist=120,
    17.         Legs=130,
    18.         Feet=140
    19.     }
    The next release will have this as the new WardrobeSlot enum. I'll add upgrade notes that people should either save their old enum, or adjust the recipes.
     
    Last edited: Jan 5, 2016
    theANMATOR2b likes this.
  29. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    Ah yes that makes perfect sense. Thanks!
     
  30. MikeyUchiha

    MikeyUchiha

    Joined:
    Jan 8, 2011
    Posts:
    109
    Hey Jaimi,

    I was wondering if you could make a video tutorial on how to get this setup.

    Thanks
     
  31. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    It might be a bit before I can get to it. It's actually pretty easy, so it shouldn't take too long. If you have any questions in the meantime, I'm happy to help out.
     
  32. MikeyUchiha

    MikeyUchiha

    Joined:
    Jan 8, 2011
    Posts:
    109
    I guess my main question is what's the order that I should do things in? Download the zip file that you posted Dec. 14 first? Does it include PBR already or do I have to add that as well? Also, will this work with Will's UMA RPG Starter Pack out of the box or will I have to make changes?

    Thanks for your support! :)
     
  33. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    No problem -

    First - get the project ready:
    1. Download the file from 12/14 above.
    2. Create a new project, and import the files.
    3. Download the PBR pack for UMA, and import it.
    4. Import Will's RPG pack.
    5. Create a standard UMA Scene, with the overlay library, slot library, etc - like in all the UMA demos.
    6. Drop the folders for Wills packs onto the SlotLibrary "add slots here" drag/drop area.
    7. Drop the same folder onto the OverlayLibrary "Add overlays here" drag/drop area.
    Second - define the recipes - this is the boring part. I've created some default wardrobe slots, and since this is just for test, it's OK to use it for now. But it's important to know that the avatar is built in the order of the WardrobeSlot enum, and if you want to add new WardrobeSlots you need to add them in order before you create recipes.

    To create a recipe, you should do this:
    1. Create a "Resources" folder, and inside that, create a "Recipes" folder
    2. In the recipes folder, right click and create a "UMA Text Recipe". You'll want to give it a name that makes some sort of sense.
    3. Add any slots to the recipe in the inspector
    4. Add the overlays for the slots.
    There's a document above that shows the different functions you can call for adding a recipe to the avatar. Think of recipes as pieces of equipment. Each WardrobeSlot can only contain one recipe, so if a slot already has a recipe in it, it will be removed.

    That should get you started!

    Edit: Uploaded some recipes for one of the peasant outfits. Not 100% sure it will find the slots/overlays! But it's worth a try.
     

    Attached Files:

    Last edited: Jan 6, 2016
  34. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    Jaimi how do I set the UMADna values like height, etc.? I see SetDNA() only takes a string so I guess this isn't it.
     
  35. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    A character can have multiple DNA classes (these are just classes that define the attributes, like "eye size" etc). By default, UMA ships with two DNA classes (one that contains all the "standard" values, and a "Tutorial" class that only contains eye spacing).

    To get *all* the DNA from all classes, you use:

    UMADnaBase[] DNA = Avatar.GetAllDNA();

    This will give you the base class of each instantiated DNA type. Then you access the Names property on each UMADnaBase to get an array of names, and call the GetValue/SetValue functions on each UMADnaBase to access the values.

    Once you've modified the DNA, you call ForceUpdate(true) to rebuild the Avatar.


    IF you want the *easy* method, you can just work with the default humaniod values. Then call GetDNAValues(); and modify them how you see fit and call ForceUpdate. In the example below, RValue is a function that gets a random value around 0.5 with the range specified. This function is not included in the code.

    Code (csharp):
    1.  
    2.  UMADnaHumanoid DNA = Avatar.GetDNAValues ();
    3.  
    4.  DNA.cheekPosition = RValue (0.75f);
    5.  DNA.cheekSize = RValue (0.75f);
    6.  DNA.chinPosition = RValue ();
    7.  DNA.chinPronounced = RValue (0.75f);
    8.  DNA.chinSize = RValue (0.75f);
    9.  DNA.lowCheekPosition = RValue (0.75f);
    10.  DNA.lowCheekPronounced = RValue (0.35f);
    11.  DNA.earsPosition = RValue ();
    12.  DNA.earsRotation = RValue (1.0f);
    13.  DNA.eyeRotation = RValue (1.0f);
    14.  DNA.eyeSize = RValue ();
    15.  DNA.earsSize = RValue (0.35f);
    16.  DNA.foreheadPosition = RValue ();
    17.  DNA.foreheadSize = RValue ();
    18.  DNA.headWidth = RValue (0.35f);
    19.  DNA.jawsPosition = RValue ();
    20.  DNA.jawsSize = RValue ();
    21.  DNA.lipsSize = RValue ();
    22.  DNA.mandibleSize = RValue (0.35f);
    23.  DNA.mouthSize = RValue ();
    24.  DNA.noseCurve = RValue (0.75f);
    25.  DNA.noseFlatten = RValue (0.75f);
    26.  DNA.noseInclination = RValue (0.35f);
    27.  DNA.nosePosition = RValue (0.3f);
    28.  DNA.nosePronounced = RValue (0.75f);
    29.  DNA.noseSize = RValue (0.3f);
    30.  DNA.noseWidth = RValue (0.5f);
    31.  
    32.  Avatar.ForceUpdate (true);
    33.  
     
    Teila likes this.
  36. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    As always Jaimi a great explanation. Thanks a bunch.
     
    Teila likes this.
  37. OHG777

    OHG777

    Joined:
    Nov 18, 2014
    Posts:
    20
    Nice! Great idea and approach Jaimi. Will definitely check this out. Thanks Teila for the heads up.
     
  38. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    I'm trying to load my character after I save it but it's just loading the base mesh. My XML I generated looks like this:

    Code (CSharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <Avatar Sex="Male">
    3. <Colors>
    4. <Hair Color="50413100" />
    5. <Eyes Color="1989F700" />
    6. <Skin Color="F9F5C700" />
    7. </Colors>
    8. <Wardrobe>
    9. <Slot Recipe="MaleBody01" />
    10. <Slot Recipe="MaleHead01" />
    11. <Slot Recipe="MaleEyes01" />
    12. <Slot Recipe="MaleHair1" />
    13. <Slot Recipe="MaleEyebrow1" />
    14. <Slot Recipe="MaleUnderwear01" />
    15. <Slot Recipe="MaleShirt" />
    16. <Slot Recipe="MaleJeans01" />
    17. </Wardrobe>
    18. <DNA>
    19. <DNAValue height="0.5019608" />
    20. <DNAValue headSize="0.5019608" />
    21. <DNAValue headWidth="0.5019608" />
    22. <DNAValue neckThickness="0.5019608" />
    23. <DNAValue armLength="0.5" />
    24. <DNAValue forearmLength="0.5" />
    25. <DNAValue armWidth="0.5" />
    26. <DNAValue forearmWidth="0.5" />
    27. <DNAValue handsSize="0.5" />
    28. <DNAValue feetSize="0.5019608" />
    29. <DNAValue legSeparation="0.5" />
    30. <DNAValue upperMuscle="0.5" />
    31. <DNAValue lowerMuscle="0.5" />
    32. <DNAValue upperWeight="0.5" />
    33. <DNAValue lowerWeight="0.5" />
    34. <DNAValue legsSize="0.5" />
    35. <DNAValue belly="0.5" />
    36. <DNAValue waist="0.5" />
    37. <DNAValue gluteusSize="0.5" />
    38. <DNAValue earsSize="0.5019608" />
    39. <DNAValue earsPosition="0.5019608" />
    40. <DNAValue earsRotation="0.5019608" />
    41. <DNAValue noseSize="0.5019608" />
    42. <DNAValue noseCurve="0.5019608" />
    43. <DNAValue noseWidth="0.5019608" />
    44. <DNAValue noseInclination="0.5019608" />
    45. <DNAValue nosePosition="0.5019608" />
    46. <DNAValue nosePronounced="0.5019608" />
    47. <DNAValue noseFlatten="0.5019608" />
    48. <DNAValue chinSize="0.5019608" />
    49. <DNAValue chinPronounced="0.5019608" />
    50. <DNAValue chinPosition="0.5019608" />
    51. <DNAValue mandibleSize="0.5019608" />
    52. <DNAValue jawsSize="0.5019608" />
    53. <DNAValue jawsPosition="0.5019608" />
    54. <DNAValue cheekSize="0.5019608" />
    55. <DNAValue cheekPosition="0.5019608" />
    56. <DNAValue lowCheekPronounced="0.5019608" />
    57. <DNAValue lowCheekPosition="0.5019608" />
    58. <DNAValue foreheadSize="0.5019608" />
    59. <DNAValue foreheadPosition="0.5019608" />
    60. <DNAValue lipsSize="0.5019608" />
    61. <DNAValue mouthSize="0.5019608" />
    62. <DNAValue eyeRotation="0.5019608" />
    63. <DNAValue eyeSize="0.5019608" />
    64. <DNAValue breastSize="0.5" />
    65. </DNA>
    66. </Avatar>
    67.  
    So the Wardrobe slots were written into the file. Then I try and load my character like this:

    Code (CSharp):
    1.  public void Load()
    2.         {
    3.             Avatar.umaRecipe = Avatar.MaleBase;
    4.             Avatar.LoadFromFile("Test.xml");
    5.  
    6.             Avatar.BuildCharacter(true);
    7.         }
    But this just gives me the base male
     
  39. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    @Hedonsoft :

    The current code looks for all XML files in a Resources/Characters Folder (it can be anywhere in your project). I'll try to tidy this up, so It can be anywhere.
     
  40. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    I created a new test project and imported only your package. I added the 2 follkwing functions to the Custimizer script:

    Code (CSharp):
    1.  public void Save()
    2.     {
    3.         string fileName = "Assets/UMA/Extensions/CharacterSystem/Resources/Characters/Test.xml";
    4.         string s = Avatar.Save();
    5.  
    6.         StreamWriter stream = File.CreateText(fileName);
    7.         stream.WriteLine(s);
    8.         stream.Close();
    9.     }
    10.  
    11.     public void Load()
    12.     {
    13.         Avatar.LoadFromFile("Test.xml");
    14.         Debug.Log("Loaded");
    15.         Avatar.BuildCharacter(true);
    16.     }
    The Test.xml gets created in the right place and looks fine. I have a button that calls Load() and the Debug fires but nothing else happens.
     
  41. BackwoodsGaming

    BackwoodsGaming

    Joined:
    Jan 2, 2014
    Posts:
    2,229
    I haven't worked with Jaimi's system yet but I'm wondering if maybe he meant for it to go in Assets/Resources/Characters. Usually that's how I interpret when someone mentions the Resources folder. Not sure though, but might be worth a try. :)
     
  42. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    LoadFromFile doesn't have a fallback yet - it expects all of the xml files to exist at startup time -- I'll fix this in the next version.

    For now the workaround is to just load the XML file manually:

    string readText = File.ReadAllText(xmlfile);
    Avatar.Load(readText);

    Also - not sure about the default path when running - might want to build a full path:

    string fileName = Path.Combine(Application.dataPath,"Assets/UMA/Extensions/CharacterSystem/Resources/Characters/Test.xml");

    edit: one more update:

    You don't need to call BuildCharacter after loading the file, it will happen automatically as part of the load process (has to, so it can update the DNA)
     
    Last edited: Jan 10, 2016
    BackwoodsGaming likes this.
  43. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    Got it thanks :) The updated Load() looks like this:
    Code (CSharp):
    1.     public void Load()
    2.     {
    3.         string xmlfile = Path.Combine(Application.dataPath, "UMA/Extensions/CharacterSystem/Resources/Characters/Test.xml");
    4.         string readText = File.ReadAllText(xmlfile);
    5.         Avatar.Load(readText);
    6.     }
    The only issue now is that the skin color always loads black but that's not a huge deal for now.
     
  44. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    Probably some issue in the color table loader... Does the avatar already have the colors before loading?
     
  45. evil_genie

    evil_genie

    Joined:
    Sep 10, 2015
    Posts:
    8
    Sorry if this is a stupid question, but :

    Can your system be used to add components at runtime like ragdolls, scritps, gameobjects, etc.?

    I'm trying to add a ragdoll to my UMA



    as well as a few other components and I've been pulling my hair out trying to figure it out...
     
    SecretAnorak likes this.
  46. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,628
    I'm not very familiar with ragdolls or colliders, but I think some of your difficulties may come from overlapping colliders. IIRC, when colliders overlap, their reactions may be energetic and unpredictable.
     
  47. evil_genie

    evil_genie

    Joined:
    Sep 10, 2015
    Posts:
    8
    Thanks for the response!
    Actually my only issue is that i dont know how to set up ragdolls on a UMA when it generates. I know I'm supposed to add components to the UMA via recipes (at least thats what the person who made the video said) but ive had trouble finding how to do that :(
     
  48. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    You can define recipes and add them at generation time, no problem:

    The first thing you do is look in Uma/Humanoid/Slots/AdditionalSlots -- these are all the "component slots". The first one - CapsuleCollider has all the pieces to show how to add recipes automatically at generation time.

    There is a "CapsuleColliderSlot" -- this is a "CharacterCompleted" event on it. This references the "CapsuleColliderSlotScript.cs", and says to call the "OnDnaApplied" function. (Yes, it's the completed event, calling the DNA Applied function, that's just the way it was created).

    In OnDnaApplied, there's some code that adds the RigidBody and CapsuleCollider if it doesn't exist.

    To make this work, just add the recipe to the "AdditionalRecipes" array on the avatar.

    This method is great when you want to create a predefined set of components, and just hand them off to be applied.​

    But it's also easy to just skip all this and do it yourself without recipes.

    On the CharacterAvatar is an event called "Character Created". To use this you would create a script to postprocess your character -- add colliders, setup the ragdoll, etc. Then attach that script to the character, and then have the event call the function on your new script. Note: Because of the nature of UMA, it's sometimes best to have the collider on the character at design time, and adjust it creation time (instead of creating it).
     
    hopeful likes this.
  49. Hedonsoft

    Hedonsoft

    Joined:
    Jul 11, 2012
    Posts:
    168
    Yes it has the colors before loading. The colors in the xml look fine.

    Code (CSharp):
    1. <Colors>
    2. <Hair Color="32291F00" />
    3. <Eyes Color="000000FF" />
    4. <Skin Color="E5E3E5FF" />
    5. </Colors>
    but when loaded the skin is all black
     
  50. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,171
    Found the bug - it's in ColorUtility.cs - the TryParseHtmllString function only works in some cases. I forgot to tell it to use Hex (Ouch!!). The correct function is below:

    Code (CSharp):
    1.        
    2.         public static bool TryParseHtmlString(string htmlcolor, out Color c)
    3.         {
    4.             if (htmlcolor.StartsWith("#"))
    5.             {
    6.                 htmlcolor = htmlcolor.Substring(1,8);
    7.             }
    8.  
    9.             if (htmlcolor.Length == 6)
    10.             {
    11.                 // add alpha
    12.                 htmlcolor += "ff";
    13.             }
    14.  
    15.             if (htmlcolor.Length == 8)
    16.             {
    17.                 try
    18.                 {
    19.                     byte r = Convert.ToByte(htmlcolor.Substring(0,2),16);
    20.                     byte g = Convert.ToByte(htmlcolor.Substring(2,2),16);
    21.                     byte b = Convert.ToByte(htmlcolor.Substring(4,2),16);
    22.                     byte a = Convert.ToByte(htmlcolor.Substring(6,2),16);
    23.                     Color32 cb = new Color32(r,g,b,a);
    24.                     c = cb;
    25.                     return true;
    26.                 }
    27.                 catch
    28.                 {
    29.                     c = Color.black;
    30.                     return false;
    31.                 }
    32.             }
    33.             c = Color.black;
    34.             return false;
    35.             }
     
    Hedonsoft and hopeful like this.