uma 实例

0、关键词解释:
Slot:a mesh which can be added to an UMA
overlay: a texture that can be added to an UMA
DNA: values that changes the shape of an UMA
Race: s set of meshes which work together to make an UMA

1、如何动态创建UMA:
关键代码:
void GenerateUMA ()
    {
        GameObject GO = new GameObject ("MyUMA");
        umaDynamicAvatar = GO.AddComponent<UMADynamicAvatar> ();

        //init avatar and grab a reference to it`s data component
        umaDynamicAvatar.Initialize ();
        umaData = umaDynamicAvatar.umaData;

        //character 创建完成后调用
        umaData.OnCharacterCreated += CharacterCreatedCallback;
        //umaData.OnCharacterDestroyed
        //umaData.OnCharacterUpdated

        // atach our generator
        umaDynamicAvatar.umaGenerator = generator;
        umaData.umaGenerator = generator;

        // set up slot array
        umaData.umaRecipe.slotDataList = new SlotData[numberOfSlots];

        // set up our Morph references
        umaDna = new UMADnaHumanoid ();
        umaTutorialDNA = new UMADnaTutorial ();
        umaData.umaRecipe.AddDna (umaDna);
        umaData.umaRecipe.AddDna (umaTutorialDNA);

        // >>> this is where the fun will happen <<<
        CreateMale ();
        umaDynamicAvatar.animationController = animController;

        // generate our UMA
        umaDynamicAvatar.UpdateNewRace ();

        GO.transform.parent = this.gameObject.transform;
        GO.transform.localPosition = Vector3.zero;
        GO.transform.localRotation = Quaternion.identity;
    }
2、如何运行过程中动态更改体型
关键代码段:
if (bodyMass != umaDna.upperMuscle) {
            SetBodyMass (bodyMass);
            umaData.isShapeDirty = true;
            umaData.Dirty ();    
   }

void SetBodyMass (float mass)
    {
        umaDna.upperMuscle = mass;
        umaDna.upperWeight = mass;
        umaDna.lowerMuscle = mass;
        umaDna.lowerWeight = mass;
        umaDna.armWidth = mass;
        umaDna.forearmWidth = mass;
    }
3、如何动态添加、删除overlay&slot,及颜色【也就是添加、更改、删除衣服】
关键代码段:
///   hair  //
        if (hairState && !lastHairState) {
            lastHairState = true;
            SetSlot (7, "M_Hair_Shaggy");
            AddOverlay (7, "M_Hair_Shaggy", hairColor);
            umaData.isMeshDirty = true;
            umaData.isShapeDirty = true;
            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

        if (!hairState && lastHairState) {
            lastHairState = false;
            RemoveSlot (7);
            //RemoveOverlay (7, "M_Hair_Shaggy");
            umaData.isMeshDirty = true;
            umaData.isShapeDirty = true;
            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

 slot helper /
    void SetSlot (int slotNumber, string slotName)
    {
        umaData.umaRecipe.slotDataList [slotNumber] = slotLibrary.InstantiateSlot (slotName);
    }

    void RemoveSlot (int slotNumber)
    {
        umaData.umaRecipe.slotDataList [slotNumber] = null;
    }

 overlay helper /
    void AddOverlay (int slot, string overlayName)
    {
        umaData.umaRecipe.slotDataList [slot].AddOverlay (overlayLibrary.InstantiateOverlay (overlayName));
    }

    void AddOverlay (int slot, string overlayName, Color color)
    {
        umaData.umaRecipe.slotDataList [slot].AddOverlay (overlayLibrary.InstantiateOverlay (overlayName, color));
    }

    void LinkOverlay (int slotNumber, int slotToLink)
    {
        umaData.umaRecipe.slotDataList [slotNumber].SetOverlayList (umaData.umaRecipe.slotDataList [slotToLink].GetOverlayList ());
    }

    void RemoveOverlay (int slotNumber, string overlayName)
    {
        umaData.umaRecipe.slotDataList [slotNumber].RemoveOverlay (overlayName);
    }

    void ColorOverlay (int slotNumber, string overlayName, Color color)
    {
        umaData.umaRecipe.slotDataList [slotNumber].SetOverlayColor (color, overlayName);
    }
4、如何导出导入UMA
//   save and load /
    void SaveTxt ()
    {
        //genarate uma string 
        UMATextRecipe recipe = ScriptableObject.CreateInstance<UMATextRecipe> ();
        recipe.Save (umaDynamicAvatar.umaData.umaRecipe, umaDynamicAvatar.context);
        SaveString = recipe.recipeString;
        Destroy (recipe);

        //save string to text file
        string fileName = "Assets/Resources/MyTestUma.txt";
        StreamWriter stream = File.CreateText (fileName);
        stream.WriteLine (SaveString);
        stream.Close ();
    }

    void LoadTxt ()
    {
        //loadstring from text.txt
        string fileName = "Assets/Resources/MyTestUma.txt";
        StreamReader stream = File.OpenText (fileName);
        SaveString = stream.ReadLine ();
        stream.Close ();

        //regenarate uma
        UMATextRecipe recipe = ScriptableObject.CreateInstance<UMATextRecipe> ();
        recipe.recipeString = SaveString;
        umaDynamicAvatar.Load (recipe);
        Destroy (recipe);
    }

    void LoadAsset ()
    {
        UMARecipeBase recipe = Resources.Load ("MyTestUmaAsset") as UMARecipeBase;  //注意这里不能有重名的文件名称
        umaDynamicAvatar.Load (recipe);
    }

    void SaveAsset ()
    {
        #if UNITY_EDITOR
        UMATextRecipe asset = ScriptableObject.CreateInstance<UMATextRecipe> ();
        asset.Save (umaDynamicAvatar.umaData.umaRecipe, umaDynamicAvatar.context);
        AssetDatabase.CreateAsset (asset, "Assets/Resources/MyTestUmaAsset.asset");
        AssetDatabase.SaveAssets ();
        #endif
    }
5、如何给UMA添加武器
思路:在创建人物模型成功后的事件中,给uma添加gameObject即可
//character 创建完成后调用
        umaData.OnCharacterCreated += CharacterCreatedCallback;
        //umaData.OnCharacterDestroyed
        //umaData.OnCharacterUpdated

    void CharacterCreatedCallback (UMAData umaData)
    {

        Debug.Log ("Character Created...");

        //attach props
        GrabStaff ();
    }
6、如何动态改变uma的表情
思路:在创建人物模型后,添加 UMAExpressionPlayer 组件,然后在update中动态设置 UMAExpressionPlayer 各个属性的值即可。
void CharacterCreatedCallback (UMAData umaData)
    {
        //ExpressionSet
        UMAExpressionSet expressionSet = umaData.umaRecipe.raceData.expressionSet;
        expressionPlayer = umaData.gameObject.AddComponent<UMAExpressionPlayer> ();
        expressionPlayer.expressionSet = expressionSet;
        expressionPlayer.umaData = umaData;
        expressionPlayer.Initialize ();
    }

在update()中添加:
        if ( expressionPlayer && happy != expressionPlayer.midBrowUp_Down) {
            expressionPlayer.midBrowUp_Down = happy;
            expressionPlayer.leftMouthSmile_Frown = happy;
            expressionPlayer.rightMouthSmile_Frown = happy;
        }

uma教程视屏资源如下:

附完整UMAmaker代码:
using UnityEngine;

using System.Collections;

using UMA;

using UMA.PoseTools;

using System.IO;

#if UNITY_EDITOR
using UnityEditor;
#endif


public class UMAMaker : MonoBehaviour
{

    public UMAGeneratorBase generator;
    public SlotLibrary slotLibrary;
    public OverlayLibrary overlayLibrary;
    public RaceLibrary raceLibrary;
    public RuntimeAnimatorController animController;

    private UMADynamicAvatar umaDynamicAvatar;
    private UMAData umaData;
    private UMADnaHumanoid umaDna;
    private UMADnaTutorial umaTutorialDNA;

    private int numberOfSlots = 20;


    [Range (0.0f, 1.0f)]
    public float bodyMass = 0.5f;
    [Range (-1.0f, 1.0f)]
    public float happy = 0f;

    public UMAExpressionPlayer expressionPlayer;
    public static string RIGHT_HAND = "Root/Global/Position/Hips/LowerBack/Spine/Spine1/RightShoulder/RightArm/RightForeArm/RightHand";



    public bool vestState = false;
    private bool lastVestState = false;

    public Color vestColor = Color.white;
    private Color lastVestColor = Color.white;


    public bool hairState = false;
    private bool lastHairState = false;
    public Color hairColor = Color.white;
    private Color lastHairColor = Color.white;

    public string SaveString;
    public bool saveTxt;
    public bool loadTxt;
    public bool saveAsset;
    public bool loadAsset;


    void Start ()
    {
        GenerateUMA ();
    }

    void Update ()
    {

        if (bodyMass != umaDna.upperMuscle) {
            SetBodyMass (bodyMass);
            umaData.isShapeDirty = true;
            umaData.Dirty ();    
        }

        //expression  这里不知道为什么会有一次 expressionPlayer为null的情形
        if ( expressionPlayer && happy != expressionPlayer.midBrowUp_Down) {
            expressionPlayer.midBrowUp_Down = happy;
            expressionPlayer.leftMouthSmile_Frown = happy;
            expressionPlayer.rightMouthSmile_Frown = happy;
        }

        ///   vest  //
        if (vestState && !lastVestState) {
            lastVestState = true;
            //注意添加顺序不同,就会有不同的影响
            AddOverlay (3, "SA_Tee", vestColor);
            AddOverlay (3, "SA_Logo");

            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

        if (!vestState && lastVestState) {
            lastVestState = false;
            RemoveOverlay (3, "SA_Tee");
            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

        if (vestColor != lastVestColor && vestState) {
            lastVestColor = vestColor;
            ColorOverlay (3, "SA_Tee", vestColor);
            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

        ///   hair  //
        if (hairState && !lastHairState) {
            lastHairState = true;
            SetSlot (7, "M_Hair_Shaggy");
            AddOverlay (7, "M_Hair_Shaggy", hairColor);
            umaData.isMeshDirty = true;
            umaData.isShapeDirty = true;
            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

        if (!hairState && lastHairState) {
            lastHairState = false;
            RemoveSlot (7);
            //RemoveOverlay (7, "M_Hair_Shaggy");
            umaData.isMeshDirty = true;
            umaData.isShapeDirty = true;
            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

        if (hairColor != lastHairColor && hairState) {
            lastHairColor = hairColor;
            ColorOverlay (7, "M_Hair_Shaggy", hairColor);
            umaData.isTextureDirty = true;
            umaData.Dirty ();
        }

        if (saveTxt) {
            saveTxt = false;
            SaveTxt ();
        }
        if (loadTxt) {
            loadTxt = false;
            LoadTxt ();
        }


        if (saveAsset) {
            saveAsset = false;
            SaveAsset ();
        }
        if (loadAsset) {
            loadAsset = false;
            LoadAsset ();
        }
    }



    void GenerateUMA ()
    {
        GameObject GO = new GameObject ("MyUMA");
        umaDynamicAvatar = GO.AddComponent<UMADynamicAvatar> ();

        //init avatar and grab a reference to it`s data component
        umaDynamicAvatar.Initialize ();
        umaData = umaDynamicAvatar.umaData;

        //character 创建完成后调用
        umaData.OnCharacterCreated += CharacterCreatedCallback;
        //umaData.OnCharacterDestroyed
        //umaData.OnCharacterUpdated

        // atach our generator
        umaDynamicAvatar.umaGenerator = generator;
        umaData.umaGenerator = generator;

        // set up slot array
        umaData.umaRecipe.slotDataList = new SlotData[numberOfSlots];

        // set up our Morph references
        umaDna = new UMADnaHumanoid ();
        umaTutorialDNA = new UMADnaTutorial ();
        umaData.umaRecipe.AddDna (umaDna);
        umaData.umaRecipe.AddDna (umaTutorialDNA);

        // >>> this is where the fun will happen <<<
        CreateMale ();
        umaDynamicAvatar.animationController = animController;

        // generate our UMA
        umaDynamicAvatar.UpdateNewRace ();

        GO.transform.parent = this.gameObject.transform;
        GO.transform.localPosition = Vector3.zero;
        GO.transform.localRotation = Quaternion.identity;
    }



    void CreateMale ()
    {
        // grab a reference to our recipe 
        var umaRecipe = umaDynamicAvatar.umaData.umaRecipe;
        umaRecipe.SetRace (raceLibrary.GetRace ("HumanMale"));


        //umaData.umaRecipe.slotDataList [0] = slotLibrary.InstantiateSlot ("MaleEyes");
        SetSlot (0, "MaleEyes");
        AddOverlay (0, "EyeOverlay");
        //umaData.umaRecipe.slotDataList [0].AddOverlay (overlayLibrary.InstantiateOverlay("EyeOverlay"));


        //umaData.umaRecipe.slotDataList [1] = slotLibrary.InstantiateSlot ("MaleInnerMouth");
        SetSlot (1, "MaleInnerMouth");  //添加脸部分的卡槽
        AddOverlay (1, "InnerMouth");  //添加脸部分的遮盖物
        //umaData.umaRecipe.slotDataList [1].AddOverlay (overlayLibrary.InstantiateOverlay("InnerMouth"));


        //umaData.umaRecipe.slotDataList [2] = slotLibrary.InstantiateSlot ("MaleFace");
        SetSlot (2, "MaleFace");
        AddOverlay (2, "MaleHead02");


        //umaData.umaRecipe.slotDataList [2].AddOverlay (overlayLibrary.InstantiateOverlay("MaleHead01"));
        //umaData.umaRecipe.slotDataList [3] = slotLibrary.InstantiateSlot ("MaleTorso");

        SetSlot (3, "MaleTorso");
        AddOverlay (3, "MaleBody02");
        //umaData.umaRecipe.slotDataList [3].AddOverlay (overlayLibrary.InstantiateOverlay("MaleBody02"));


        //umaData.umaRecipe.slotDataList [4] = slotLibrary.InstantiateSlot ("MaleHands");
        SetSlot (4, "MaleHands");

        //umaData.umaRecipe.slotDataList [4].AddOverlay (overlayLibrary.InstantiateOverlay ("MaleBody02"));
        umaData.umaRecipe.slotDataList [4].SetOverlayList (umaData.umaRecipe.slotDataList [3].GetOverlayList ());


        //umaData.umaRecipe.slotDataList [5] = slotLibrary.InstantiateSlot ("MaleLegs");
        SetSlot (5, "MaleLegs");

        //umaData.umaRecipe.slotDataList [5].AddOverlay (overlayLibrary.InstantiateOverlay("MaleBody02"));
        umaData.umaRecipe.slotDataList [5].SetOverlayList (umaData.umaRecipe.slotDataList [3].GetOverlayList ());


        //umaData.umaRecipe.slotDataList [6] = slotLibrary.InstantiateSlot ("MaleFeet");
        SetSlot (6, "MaleFeet");

        //umaData.umaRecipe.slotDataList [6].AddOverlay (overlayLibrary.InstantiateOverlay("MaleBody02"));
        umaData.umaRecipe.slotDataList [6].SetOverlayList (umaData.umaRecipe.slotDataList [3].GetOverlayList ());


        AddOverlay (3, "MaleUnderwear01");
        //umaData.umaRecipe.slotDataList [3].AddOverlay (overlayLibrary.InstantiateOverlay("MaleUnderwear01"));
        //umaData.umaRecipe.slotDataList [5].AddOverlay (overlayLibrary.InstantiateOverlay("MaleUnderwear01"));


        umaData.umaRecipe.slotDataList [2].AddOverlay (overlayLibrary.InstantiateOverlay ("MaleEyebrow01", Color.black));
        AddOverlay (2, "MaleEyebrow01", Color.black); //眉毛颜色
        AddOverlay (3, "MaleUnderwear01");  //添加裤子

        //AddOverlay (3, "SA_Tee");  //添加T恤
        //AddOverlay(3,"SA_Logo");    //添加logo

        //SetSlot(12,"MSimpleLeatherShoes");
        //AddOverlay(12,"MSimpleLeatherShoes");


        SetSlot (6, "MSimpleLeatherShoes");
        AddOverlay (6, "MSimpleLeatherShoes");


        //SetSlot(7,"CowboyHat");
        //AddOverlay(7,"CowboyHat");
    }



    void SetBodyMass (float mass)
    {
        umaDna.upperMuscle = mass;
        umaDna.upperWeight = mass;
        umaDna.lowerMuscle = mass;
        umaDna.lowerWeight = mass;
        umaDna.armWidth = mass;
        umaDna.forearmWidth = mass;
    }

     overlay helper /
    void AddOverlay (int slot, string overlayName)
    {
        umaData.umaRecipe.slotDataList [slot].AddOverlay (overlayLibrary.InstantiateOverlay (overlayName));
    }

    void AddOverlay (int slot, string overlayName, Color color)
    {
        umaData.umaRecipe.slotDataList [slot].AddOverlay (overlayLibrary.InstantiateOverlay (overlayName, color));
    }

    void LinkOverlay (int slotNumber, int slotToLink)
    {
        umaData.umaRecipe.slotDataList [slotNumber].SetOverlayList (umaData.umaRecipe.slotDataList [slotToLink].GetOverlayList ());
    }

    void RemoveOverlay (int slotNumber, string overlayName)
    {
        umaData.umaRecipe.slotDataList [slotNumber].RemoveOverlay (overlayName);
    }

    void ColorOverlay (int slotNumber, string overlayName, Color color)
    {
        umaData.umaRecipe.slotDataList [slotNumber].SetOverlayColor (color, overlayName);
    }

     slot helper /
    void SetSlot (int slotNumber, string slotName)
    {
        umaData.umaRecipe.slotDataList [slotNumber] = slotLibrary.InstantiateSlot (slotName);
    }

    void RemoveSlot (int slotNumber)
    {
        umaData.umaRecipe.slotDataList [slotNumber] = null;
    }


    void CharacterCreatedCallback (UMAData umaData)
    {

        Debug.Log ("Character Created...");

        //attach props
        GrabStaff ();
    
        //ExpressionSet
        UMAExpressionSet expressionSet = umaData.umaRecipe.raceData.expressionSet;
        expressionPlayer = umaData.gameObject.AddComponent<UMAExpressionPlayer> ();
        expressionPlayer.expressionSet = expressionSet;
        expressionPlayer.umaData = umaData;
        expressionPlayer.Initialize ();

        //blinkding and look around
        expressionPlayer.enableBlinking = true;
        expressionPlayer.enableSaccades = true;


        GameObject GO = transform.Find ("MyUMA").gameObject;
        //GO.AddComponent<SwordLight> ();
    }



    void GrabStaff ()
    {
        GameObject staff = GameObject.Find ("Sword");
        Transform hand = umaDynamicAvatar.gameObject.transform.FindChild (UMAMaker.RIGHT_HAND);
        staff.transform.SetParent (hand);
        staff.transform.localPosition = new Vector3 (-0.103f, -0.127f, -0.066f);
        staff.transform.localRotation = Quaternion.Euler (new Vector3 (12.607f, 0, 0));
    }


    //   save and load /
    void SaveTxt ()
    {
        //genarate uma string 
        UMATextRecipe recipe = ScriptableObject.CreateInstance<UMATextRecipe> ();
        recipe.Save (umaDynamicAvatar.umaData.umaRecipe, umaDynamicAvatar.context);
        SaveString = recipe.recipeString;
        Destroy (recipe);

        //save string to text file
        string fileName = "Assets/Resources/MyTestUma.txt";
        StreamWriter stream = File.CreateText (fileName);
        stream.WriteLine (SaveString);
        stream.Close ();
    }

    void LoadTxt ()
    {
        //loadstring from text.txt
        string fileName = "Assets/Resources/MyTestUma.txt";
        StreamReader stream = File.OpenText (fileName);
        SaveString = stream.ReadLine ();
        stream.Close ();

        //regenarate uma
        UMATextRecipe recipe = ScriptableObject.CreateInstance<UMATextRecipe> ();
        recipe.recipeString = SaveString;
        umaDynamicAvatar.Load (recipe);
        Destroy (recipe);
    }

    void LoadAsset ()
    {
        UMARecipeBase recipe = Resources.Load ("MyTestUmaAsset") as UMARecipeBase;  //注意这里不能有重名的文件名称
        umaDynamicAvatar.Load (recipe);
    }

    void SaveAsset ()
    {
        #if UNITY_EDITOR
        UMATextRecipe asset = ScriptableObject.CreateInstance<UMATextRecipe> ();
        asset.Save (umaDynamicAvatar.umaData.umaRecipe, umaDynamicAvatar.context);
        AssetDatabase.CreateAsset (asset, "Assets/Resources/MyTestUmaAsset.asset");
        AssetDatabase.SaveAssets ();
        #endif
    }

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值