Unity实现换装功能

换装的核心思想:更换对象SkinnerMeshRenderer组件中骨骼(Bones),网格(sharedMesh),材质(materials)。麻烦的是要找到对应的部位,对应的SkinnerMeshRenderer组件,对应的位置。以下,介绍一种比较简单的换装过程。

通常要实现换装需要有一个带有“所有需要更换部件”的模型,如下:(图1)中FemaleModel为模型,其中Female_Hips为骨骼信息。(图2)为场景用的样子,可以看出它是很多重复部件的叠加物。


接下来说说具体的思路;

1.先制作骨骼模型

2.将原模型和骨骼模型实例化出来

3.建立字典存储所有SkinnerMeshRenderer信息

4.建立字典存储所有骨骼信息

5.将相应的信息存储在字典中

6.以名字进行一一对应,更换相应SkinnerMeshRenderer中三大件


接下来是每步详细步骤:

1.先制作骨骼模型

其实这部很简单,只需要将原模型中所有部件删除,只留下骨骼部分,如图:其中FemaleTarget就是骨骼模型


2.将原模型和骨骼模型实例化出来

    //原模型

    GameObject avatarModel;

    //骨骼模型

    GameObject avatarTarget;

    //所有骨骼信息

    Transform[] Hips;

void InitSys() {

 //实例化对应的模型并将其隐藏 

 avatarModel = Instantiate(Resources.Load("FemaleModel") as GameObject); avatarModel.SetActive(false); 

 //实例化要显示的对象并将其所有(骨骼)Transform信息收集 

 avatarTarget = Instantiate(Resources.Load("FemaleTarget") as GameObject); 

 Hips = avatarTarget.GetComponentsInChildren();

    }

3.建立字典存储所有SkinnerMeshRenderer信息

//存储模型的所有信息 //建立字典存储模型的SkinnerMeshRenderer信息

Dictionary> avaStr = new Dictionary>();

4.建立字典存储所有骨骼信息

//建立字典存储要显示对象的skinnerMeshRenderer信息

Dictionary avaSmr = new Dictionary();

5.将相应的信息存储在字典中

void SaveAvatarData() {

    SkinnedMeshRenderer[] skis = avatarModel.GetComponentsInChildren();

    foreach (SkinnedMeshRenderer ski in skis) {

    string[] names = ski.name.Split('-');

    //如果字典中没有存储这个部位

    if (!avaStr.ContainsKey(names[0])) {

    //那么就新建一个对象当做这个对象

    GameObject part = new GameObject();

    part.name = names[0];

    //set父级为要显示的任务骨骼

    part.transform.parent = avatarTarget.transform;

    //并且给它添加ski组件并加入字典中

    avaSmr.Add(names[0], part.AddComponent());

    //存入模型字典并实例化相应子字典

    avaStr.Add(names[0], new Dictionary());

    }

    //将序号和SkinnerMeshRenderer信息存入模型字典

    avaStr[names[0]].Add(names[1], ski); } }

6.以名字进行一一对应,更换相应SkinnerMeshRenderer中三大件

 //换装 

 //参数:换装部位名称,序号 

 void ChangeMesh(string name,string num) { 

 //从模型字典中拿到相应的SkinnerMeshRenderer 

 SkinnedMeshRenderer skm = avaStr[name][num]; 

 //创建集合来存储(骨骼)Transform信息

List<Transform> bones = new List<Transform>();

        foreach (var trans in skm.bones)

        {

            foreach (var bone in Hips)

            {

                if (bone.name == trans.name)

                {

                    bones.Add(trans);

                    break;

                }

            }

        }

        avaSmr[name].bones = bones.ToArray();

        avaSmr[name].materials = skm.materials;

        avaSmr[name].sharedMesh = skm.sharedMesh;

    }

至此,基本的换装的过程就此基本完成,接下来就是让要显示的模型有一个初始状态

7.先建立字典存储模型最初的状态:

//显示初始状态

    //建立数组

    string[,] avatar = new string[,] { {"face","1" }, { "top", "1" }, { "pants", "1" }, { "hair", "1" },

        { "eyes", "1" }, { "shoes", "1" } };

8.依次调用换装方法(注意此处遍历的是数组的行数而不是数组长度)

void InitAvatar()

    {

        for (int i = 0; i < avatar.GetLength(0); i++)

        {

            ChangeMesh(avatar[i, 0], avatar[i, 1]);

        }

    }

好了,现在试下调用如上方法就可以让模型显示出来啦。

void Start () {

        InitSys();

        SaveAvatarData();

        InitAvatar();

    }


进行换装就是调用ChangeMesh方法就好。如下举个小栗子~

void Update () {

        print(ani.isPlaying);

        if (Input.GetKeyDown(KeyCode.Space))

        {

            ChangeMesh("top", "2");

        }

}


Ps:这里还有一个问题就是模型的动画没有播放出来(虽然ani.isPlaying结果是true)。我怀疑是我中途换了Unity版本导致。就不深究啦~~

如上如果有任何不严谨或是错误的地方,欢迎各位指正~~嘻嘻~~

                                                                                                                                                                                                不忘初心的Tiny

                

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 最近都比较忙,没时间写,今晚利用空余时间分享一下游戏开发中常用的“换装”给大家,如果大家有什么好的插件或想法,记得...
    光明程辉阅读 5,360评论 1 7
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 表妹毕业了,终于拿到了国际贸易专业的硕士毕业证书,而且英语专六,这样的底牌通过努力足以配得上她的未来。 家人不担心...
    Ms妮子眯眯阅读 611评论 0 2
  • http请求过程 域名解析 发起TCP的三次握手 建立TCP连接后发起 http 请求 服务器响应 http 请求...
    Sharise_Mo佩珊阅读 745评论 0 0
  • 不知道什么时候开始有一种丧文化悄然流行开来。 这些网络用语我相信大家应该听过不少。 什么“世上无难事,只要肯放弃”...
    诗人漫步uu阅读 400评论 0 1