Unity 保存场景物体修改到Prefab
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 保存场景物体修改到Prefab相关的知识,希望对你有一定的参考价值。
参考技术A 有时候会在场景中修改大量的prefab的实例物体,然后又需要同步到prefab上,这个脚本就非常有用了:Unity角色换装问题
游戏中经常涉及到角色换装问题。
1.装备模型中的每一套装备都必须使用同一套骨骼,把单个骨骼数据保存成Prefab,骨骼数据在Unity中以Transform形式存在
2.把模型中的每个部分都单独保存成prefab。
实现思路:
1.创建骨骼GameObject,把所有的装备蒙皮数据合并到一个prefab中。
2.创建装备GameObject,用来手机其中蒙皮数据,从而创建新的SkinedMeshRenderer。
收集信息代码
// Collect information from meshes for (int i = 0; i < meshes.Length; i ++) { SkinnedMeshRenderer smr = meshes[i]; materials.AddRange(smr.materials); // Collect materials // Collect meshes for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++) { CombineInstance ci = new CombineInstance(); ci.mesh = smr.sharedMesh; ci.subMeshIndex = sub; combineInstances.Add(ci); } // Collect bones for (int j = 0 ; j < smr.bones.Length; j ++) { int tBase = 0; for (tBase = 0; tBase < transforms.Count; tBase ++) { if (smr.bones[j].name.Equals(transforms[tBase].name)) { bones.Add(transforms[tBase]); break; } } } }
为新的骨骼生成SkinnedMeshRenderer。
// Create a new SkinnedMeshRenderer SkinnedMeshRenderer oldSKinned = skeleton.GetComponent<SkinnedMeshRenderer> (); if (oldSKinned != null) { GameObject.DestroyImmediate (oldSKinned); } SkinnedMeshRenderer r = skeleton.AddComponent<SkinnedMeshRenderer>(); r.sharedMesh = new Mesh(); r.sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false);// Combine meshes r.bones = bones.ToArray();// Use new bones
挂载武器
Transform[] transforms = Instance.GetComponentsInChildren<Transform>(); foreach (Transform joint in transforms) { if (joint.name == "weapon_hand_r") {// find the joint (need the support of art designer) WeaponInstance.transform.parent = joint.gameObject.transform; break; } }
这里涉及到一个优化,合并出来的新的skinned Mesh Renderer中有所有部位的materials,
这里我们可以吧materials合并成一个,减少DrawCall,但是同样会增加内存,在具体项目中,可以结合实际情况进行优化,
// merge materials if (combine) { newMaterial = new Material (Shader.Find ("Mobile/Diffuse")); oldUV = new List<Vector2[]>(); // merge the texture List<Texture2D> Textures = new List<Texture2D>(); for (int i = 0; i < materials.Count; i++) { Textures.Add(materials[i].GetTexture(COMBINE_DIFFUSE_TEXTURE) as Texture2D); } newDiffuseTex = new Texture2D(COMBINE_TEXTURE_MAX, COMBINE_TEXTURE_MAX, TextureFormat.RGBA32, true); Rect[] uvs = newDiffuseTex.PackTextures(Textures.ToArray(), 0); newMaterial.mainTexture = newDiffuseTex; // reset uv Vector2[] uva, uvb; for (int j = 0; j < combineInstances.Count; j++) { uva = (Vector2[])(combineInstances[j].mesh.uv); uvb = new Vector2[uva.Length]; for (int k = 0; k < uva.Length; k++) { uvb[k] = new Vector2((uva[k].x * uvs[j].width) + uvs[j].x, (uva[k].y * uvs[j].height) + uvs[j].y); } oldUV.Add(combineInstances[j].mesh.uv); combineInstances[j].mesh.uv = uvb; } }
此方式是参考网上分析,原作者GitHub:https://github.com/zouchunyi/UnityAvater
以上是关于Unity 保存场景物体修改到Prefab的主要内容,如果未能解决你的问题,请参考以下文章