动态修改SkinnedMeshRenderer顶点(本质上还是修改Mesh)
实现人物带上帽子后,当前发型头发突出帽子的模型部分会被缩至帽子内部解决了头发穿透帽子模型的问题
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ChangeHairTool : MonoBehaviour { public Transform hatWomanCenterTrans;//女帽点 public Transform hatManCenterTrans;//男帽点 Vector3 hatV3;//帽子实时坐标 public bool isMan = true;//区分男女 帽子高度不同 public float factor1 = 0.01f;//头发形变速度,速度越大,变化越大 public float factor2 = 0.09f;//可受影响的头发高度 public float radius1 = 0.12f;//帽子包住头发的最大半径(帽子以上) public float radius2 = 0.09f;//长发专用用于控制下半部分头发(帽子以下) public float hatAngelX = 15f;//帽子X轴旋转角度 public float hatAngelZ = 0;//帽子Z轴旋转角度 public Dictionary<SkinnedMeshRenderer, Vector3[]> svDict;//原顶点坐标 private void Awake() { svDict = new Dictionary<SkinnedMeshRenderer, Vector3[]>(); if (isMan) { hatV3 = hatManCenterTrans.position; } else { hatV3 = hatWomanCenterTrans.position; } } /// <summary> /// 还原头发 /// </summary> public void OnClickBtn(Transform trans) { if (trans.GetComponentInChildren<SkinnedMeshRenderer>()) { foreach (SkinnedMeshRenderer item in trans.GetComponentsInChildren<SkinnedMeshRenderer>()) { item.sharedMesh.vertices = svDict[item]; } } } public void ChangeHair(Transform trans) { svDict.Clear(); if (trans.GetComponentInChildren<SkinnedMeshRenderer>()) { foreach (var item in trans.GetComponentsInChildren<SkinnedMeshRenderer>()) { ChangeHair(item); } } } /// <summary> /// 改变头发适应帽子 /// </summary> public void ChangeHair(SkinnedMeshRenderer smr) { svDict.Add(smr, smr.sharedMesh.vertices); Vector3[] vertices = smr.sharedMesh.vertices; for (var i = 0; i < vertices.Length; i++) { Vector3 toCenterDir = Vector3.Normalize(hatManCenterTrans.position - vertices[i]); float d = Mathf.Sin(hatAngelZ * (Mathf.PI) / 180) * vertices[i].x + Mathf.Sin(hatAngelX * (Mathf.PI) / 180) * vertices[i].z; float newy = hatV3.y + d; //Debug.Log(d); if (vertices[i].y > newy) { float moveDis = Vector3.Distance(hatManCenterTrans.position, vertices[i]); float moveDisM = 0 > moveDis - radius1 ? 0 : moveDis - radius1; Vector3 moveVector = toCenterDir * moveDisM; vertices[i] += moveVector; } else { Vector3 center = new Vector3(hatV3.x, vertices[i].y, hatV3.z); Vector3 toCenterDirr = Vector3.Normalize(center - vertices[i]); Vector3 vv = (Mathf.Sqrt(Mathf.Pow((hatV3.x - vertices[i].x), 2) + Mathf.Pow((hatV3.z - vertices[i].z), 2)) / Mathf.Cos(hatAngelX * (Mathf.PI) / 180) - radius2) * toCenterDirr; //Debug.Log(Mathf.Sqrt(Mathf.Pow((hatV3.x - vertices[i].x), 2) + Mathf.Pow((hatV3.z - vertices[i].z), 2))); //Debug.Log(vv); float centerDis2 = Vector3.Distance(vv, vertices[i]); float h = (0 > factor2 - Mathf.Abs(vertices[i].y - hatV3.y) ? 0 : factor2 - Mathf.Abs(vertices[i].y - hatV3.y)) * factor1; float moveDistance2 = (0 > centerDis2 - radius2 ? 0 : centerDis2 - radius2) * h; Vector3 moveVector2 = toCenterDirr * moveDistance2; vertices[i] += moveVector2; } } smr.sharedMesh.vertices = vertices; } }