zoukankan      html  css  js  c++  java
  • unity换装系统+网格合并

    这里的做法是模型把所有衣服全部穿上作为一个资源

    然后还有一个只有骨骼信息的骨架资源

    将这2个制作好了Prefab

    模型部件数据

    资源数据

    【代码】

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class AvatarSystem : MonoBehaviour {
    
        //模型全文件
        GameObject modelObject;
        Transform modelSource;
        //骨骼文件
        GameObject targetSource;
        Transform targetTrans;
        //Data字典 存储source的各种信息;
        private Dictionary<string, Dictionary<string, Transform>> data = new Dictionary<string, Dictionary<string, Transform>>();
        //targetSmr字典 存储目标的骨骼信息
        private Dictionary<string, SkinnedMeshRenderer> targetSmr = new Dictionary<string, SkinnedMeshRenderer>();
        //骨骼数组
        private Transform[] hips;
        //套装数据
        string[,] avatarStr = new string[,] { { "Glove", "suit01" }, { "Head", "suit01" }, { "Hair", "suit01" }, { "Body", "suit02" }, { "Leg", "suit03" }, { "Shoe", "suit03" } };
    
        // Use this for initialization
        void Start () {
            InstantiateAvatar("Prefab/Model_girl");//读取模型文件
            InstantiateSkeleton("Prefab/Target_girl");//读取骨架文件
            LoadAvatarData(modelSource);//读取模型所有衣服数据,并且存储
            hips = targetTrans.GetComponentsInChildren<Transform>();//拿取人物骨骼信息
            Inivatar(avatarStr);//换上套装
            //targetSource.AddComponent<Animator>();
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    
    
        //实例化来源
        void InstantiateAvatar(string modelName)
        {
            //必需得实例化出来,不然无法获得数据
            modelObject = (Instantiate(Resources.Load<GameObject>(modelName)));
            modelSource = modelObject.transform;
            modelSource.gameObject.SetActive(false);//隐藏
            //Destroy(modelObject);//销毁
        }
        //实例化骨架(换装就是在骨架上加衣服)
        void InstantiateSkeleton(string targetName)
        {
            targetSource = Instantiate(Resources.Load<GameObject>(targetName));
            targetTrans = targetSource.transform;
        }
        //读取来源的各种信息(source模型源文件)
        void LoadAvatarData(Transform source)
        {
            if (source == null)
            {
                return;
            }
            SkinnedMeshRenderer[] parts = source.GetComponentsInChildren<SkinnedMeshRenderer>(true);
            foreach (SkinnedMeshRenderer part in parts)
            {
                string[] partName = part.name.Split('_');
                if (!data.ContainsKey(partName[0]))
                {
                    data.Add(partName[0], new Dictionary<string, Transform>());
                    GameObject partObj = new GameObject();
                    partObj.name = partName[0];
                    partObj.transform.parent = targetTrans;
                    targetSmr.Add(partName[0], partObj.AddComponent<SkinnedMeshRenderer>());
                }
                data[partName[0]].Add(partName[1], part.transform);
            }
        }
        //更改Mesh
        public void ChangeMesh(string part, string item)
        {
            SkinnedMeshRenderer smr = data[part][item].GetComponent<SkinnedMeshRenderer>();
            //网格合并
            List<CombineInstance> combineInstances = new List<CombineInstance>();
            for (int i = 0; i < smr.sharedMesh.subMeshCount; i++)
            {
                CombineInstance ci = new CombineInstance();
                ci.mesh = smr.sharedMesh;
                ci.subMeshIndex = i;
                combineInstances.Add(ci);
            }
            List<Transform> bones = new List<Transform>();
            foreach (Transform bone in smr.bones)
            {
                foreach (Transform hip in hips)
                {
                    if (hip.name != bone.name)
                    {
                        continue;
                    }
                    bones.Add(hip);
                    break;
                }
            }
    
            //网格合并方式
            targetSmr[part].sharedMesh = new Mesh();
            targetSmr[part].sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false);
            //非网格合并方式
            //targetSmr[part].sharedMesh = smr.sharedMesh;
            targetSmr[part].bones = bones.ToArray();
            targetSmr[part].materials = smr.materials;
    
    
        }
    
        /// <summary>
        /// 换装(换1件到多件)
        /// </summary>
        /// <param name="avatarStr"></param>
        public void Inivatar(string[,] avatarStr)
        {
            int nLength = avatarStr.GetLength(0);
            for (int i = 0; i < nLength; i++)
            {
                ChangeMesh(avatarStr[i, 0], avatarStr[i, 1]);
            }
        }
    }
  • 相关阅读:
    QTP模拟鼠标和键盘事件整理
    Linux 入门常用命令 — 改变文件或目录的访问权限
    做一个有品质的男人
    Linux下.tar .gz .tgz .bz2 .bz等解、压包命令详解
    全面整理CentOS系统使用中文
    MSDN宝藏库中,初学者应该看的东西【整理的很辛苦哦】
    IIS 7.5版本中一些诡异问题的解决方案
    老生常谈ASP.NET中的Cookies,罗列读写Cookies的方法
    分享3段平时很实用的微代码,高手莫喷
    SQL 2005中的临时表
  • 原文地址:https://www.cnblogs.com/sanyejun/p/9110886.html
Copyright © 2011-2022 走看看