unity3d 换装

 
 

1.基础
BuildPipeline.BuildAssetBundle 把gameobject生成包,可以用于替换和更新
www.assetBundle 动态载入包
SkinnedMeshRenderer 骨骼模型渲染器,美术导出的时候每个子模型都带SkinnedMeshRenderer


2.基础模型生成
基础模型是从characters目录下找fbx模型(名称里面不带@),如果找到(如female.fbx),则把模型下所有有SkinnedMeshRenderer的gameobject删除,然后给模型本身加了个SkinnedMeshRenderer。
因为female是带animation的,所以这样一个基础模型就生成了,此模型带animations, 并且带一个SkinnedMeshRenderer。

 


3.子模型包的生成
子模型包是根据前面找到的fbx模型的子模型,主要包括face, eye, shoes, top ,pants, hair几个部分,子模型包包括三个部分:一个pretab,用到的所有的material, bonenames,

 


4.生成过程
生成过程主要在两个函数:
public GameObject Generate() //生成基础模型
public GameObject Generate(GameObject root) //生成root下的子模型
每一个子模型包对应的类是CharacterElement,整个模型的构成过程,就是集合所有子模型SkinnedMeshRenderer的materials, mesh的CombineInstance,还有bonenames,
SkinnedMeshRenderer r = root.GetComponent();
r.sharedMesh = new Mesh();
r.sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false);
r.bones = bones.ToArray();
r.materials = materials.ToArray();
全部赋值到了基础模型的SkinnedMeshRenderer上

 


5. SkinedMeshRender:该对象负责网格绘制(一般用于骨骼)。主要数据成员包括

 

var bones : Transform[] 骨骼

 

var materials : Material[] 材质

 

var sharedMesh : Mesh 网格

 

其中Mesh的主要成员是

 

vertices : Vector3[] 顶点

 

boneWeights : BoneWeight[] 骨骼权重

 

boneWeights数组与vertices数组对应,表示对应下标的顶点运动受骨骼影响的权重。BoenWeight结构记录了骨骼在SkinedMeshRender.bones数组中的索引。

 

 

 

6.网格和材质的对应关系

 

一张实际的网格只能施加一个材质。因此,当render所使用的mesh包含多个实际网格(sub mesh),它对每个sub mesh所施加的材质实际上是materials数组中对应下标的材质,这个对应关系一定要正确。合并网格(CombineMeshes)函数的第二个参数是设置是否将多个子网格合并成一张实际的网格。正如前面所述,一个实际的网格只能施加一个材质,所以只有被合并的所有网格原来使用的就是同一个材质(即共享材质)时,将它们真正合并才能正确应用材质。否则,应该将该参数置为false,表示不实际合并这些sub mesh,而是将它们作为被合并后Mesh对象的sub mesh。

 

转自:

http://blog.sina.com.cn/s/blog_675c4e8b0101m42a.html

 

7. 合并网格(CombineMeshes)函数的第二个参数是设置是否将多个子网格合并成一张实际的网格。正如前面所述,一个实际的网格只能施加一个材质, 所以只有被合并的所有网格原来使用的就是同一个材质(即共享材质)时,将它们真正合并才能正确应用材质。否则,应该将该参数置为false,表示不实际合 并这些sub mesh,而是将它们作为被合并后Mesh对象的sub mesh。
四、数组对应问题:网格顶点和骨骼、sub mesh和材质之间的对应都是通过数组下标进行的,所以操作时保证新生成的个数组下标对应关系正确是非常重要的。

这是例子中组合创建模型的主要函数,我将自己理解后的备注添加在里面。

1.// Creates a character based on the currentConfiguration recycling a
2.// character base, this way the position and animation of the character
3.// are not changed.
4.// 这个函数实际上并没有将各部分的子网格合并成一张网,而只是将他们合并到
5.// 同一个Mesh下作为sub mesh。因为一张网格只能用一个材质,只有所有子网格
6.// 都共享同一个材质时,合并成一张网才能保证材质应用正确。
7.
8.public GameObject Generate(GameObject root) {
9.
10.    // The SkinnedMeshRenderers that will make up a character will be
11.    // combined into one SkinnedMeshRenderers using multiple materials.
12.    // This will speed up rendering the resulting character.
13.    List<CombineInstance> combineInstances = new List<CombineInstance>();
14.    List<Material> materials = new List<Material>();
15.    List<Transform> bones = new List<Transform>();
16.
17.    //获得构成骨架的所有Transform
18.    Transform[] transforms = root.GetComponentsInChildren<Transform>();
19.    
20.    //一次处理构成身体的各部分
21.    foreach (CharacterElement element in currentConfiguration.Values)
22.    {
23.        //GetSkinnedMeshRenderer()内部Instantiat了一个由该部分肢体Assets构成的
24.        //GameObject,并返回Unity自动为其创建SinkedMeshRender。
25.        SkinnedMeshRenderer smr = element.GetSkinnedMeshRenderer();
26.
27.        //注意smr.materials中包含的材质数量和顺序与下面的sub mesh是对应的
28.        materials.AddRange(smr.materials);
29.        for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
30.        {
31.            CombineInstance ci = new CombineInstance();
32.            ci.mesh = smr.sharedMesh;
33.            ci.subMeshIndex = sub;
34.            combineInstances.Add(ci);
35.        }
36.
37.        // As the SkinnedMeshRenders are stored in assetbundles that do not
38.        // contain their bones (those are stored in the characterbase assetbundles)
39.        // we need to collect references to the bones we are using
40.        // 网格点与骨骼的对应关系是通过Mesh数据结构中的BoneWeight数组来实现的。该数组
41.        // 与网格顶点数组对应,记录了每个网格点受骨骼(骨骼记录在SinkedMeshRender的bones
42.        // 数组中,按下标索引)影响的权重。
43.        // 而此处,示例程序提供的肢体Assets并不包含骨骼,而是返回骨骼名称。因此,推断
44.        // GetBoneNames()返回的骨骼名称应该与实际骨骼数组的顺序相同。
45.        foreach (string bone in element.GetBoneNames())
46.        {
47.            foreach (Transform transform in transforms)
48.            {
49.                //通过名字找到实际的骨骼
50.                if (transform.name != bone) continue;
51.                bones.Add(transform);
52.                break;
53.            }
54.        }
55.
56.        Object.Destroy(smr.gameObject);
57.    }
58.
59.    // Obtain and configure the SkinnedMeshRenderer attached to
60.    // the character base.
61.    // 至此,combineInstances、bones和materials三个数组中的数据对应关系是正确的。
62.    // 合并时,第二个参数是fals,表示保持子网格不变,只不过将它们统一到一个Mesh里
63.    // 来管理,这样只需采用一个SkinedMeshRender绘制,效率较高。
64.    SkinnedMeshRenderer r = root.GetComponent<SkinnedMeshRenderer>();
65.    r.sharedMesh = new Mesh();
66.    r.sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false);
67.    r.bones = bones.ToArray();
68.    r.materials = materials.ToArray();
69.    
70.    return root;
71.}

 

转自:

 http://www.cnblogs.com/oldman/articles/2395518.html

你可能感兴趣的:(unity3d)