unity角色換裝的關鍵是更改角色部位上的物體的SkinnedMeshRenderer組件的屬性:
更改mesh:mesh決定了部位的物體的外形,是主要的數據。
刷新骨骼:同一個部位下,不同的mesh受到的不同的骨骼的影響不同,因此更換mesh之后,還要更新SkinnedMeshRenderer下的骨骼列表的信息,也就是更換骨骼列表。
替換材質:一個SkinnedMeshRenderer下由多個材質作用,因此還需要更換材質列表。
操作過程為,從預制物體中獲取的需要更換的相關部位的mesh,然后通過從預制物體的相關部位的SkinnedMeshRenderer下獲取到影響該部位的骨骼列表,然后從場景角色的骨骼下獲取到同名的骨骼列表,將該骨骼列表賦予到場景下角色的部位的SkinnedMeshRenderer下,並且獲取到預制物體下該部位的材質列表,同樣的將該列表賦予場景下角色的部位的SkinnedMeshRenderer下。
為了獲取到更換的信息,需要由預制物體存儲物體的相關信息。預制物體如下,每個部位下所有的物體都呈現,便於程序提取信息。

原模型如下:

場景下角色如下:

具體代碼如下:
該腳本可以放在任何地方
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AvatarSysDemo00 : MonoBehaviour { public Transform role;//場景中的角色物體 public GameObject rolePrefab;//預制物體 public GameObject kuzi;//場景中角色物體下褲子物體 public string[] kuziNames;//所有的用於替換的褲子的名字,用於再預制物體中找到相關的物體的信息 public GameObject[] objs;//褲子相關的預制物體 int index = 0;//當前的裝備索引 public Transform[] hips;//角色的骨骼物體 private void Awake() { hips = null; if (role) hips = role.GetComponentsInChildren<Transform>();//首先獲取場景中角色下的骨骼列表 for (int i = 0; i < kuziNames.Length; i++)//獲取預制物體下的所有褲子物體 { Transform kuziObj = rolePrefab.transform.Find(kuziNames[i]); objs[i] = kuziObj.gameObject; } } // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.Space))//設置為按下空格就切換一下褲子 { Debug.Log(objs.Length); if (objs.Length == 0) return; index = (index + 1) % objs.Length; ChangeMesh(objs[index]); } } //換裝 public void ChangeMesh(GameObject part) { SkinnedMeshRenderer smr = part.GetComponent<SkinnedMeshRenderer>();//獲取預制物體下相關部位的SkinnedMeshRenderer //獲取角色物體下與預制物體相關更換的Mesh部位下作用於該Mesh,再場景中與其同名的骨骼列表 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; } } kuzi.GetComponent<SkinnedMeshRenderer>().sharedMesh = smr.sharedMesh;//更改mesh kuzi.GetComponent<SkinnedMeshRenderer>().bones = bones.ToArray();//更換(刷新)骨骼列表 kuzi.GetComponent<SkinnedMeshRenderer>().materials = smr.sharedMaterials;//更換材質 } }
