using System; using System.Collections.Generic; using System.Text; using UnityEngine; using Thousandto.Core.Base; using Thousandto.Core.Support; /// /// 骨骼布料化 -- 动作柔化 /// public class BoneCloth : MonoBehaviour { public Transform m_srcRoot = null; public Transform m_dstRoot = null; public Particle[] m_particles = null; //父改变 private bool m_parentChanged = false; #region//重写MonoBehaviour方法 //每帧更新最后 private void LateUpdate() { if (m_parentChanged) { m_parentChanged = false; ResetPose(); } if (m_particles != null) { for (int i = 0; i < m_particles.Length; ++i) { var p = m_particles[i]; if (p.pfactor < 0.99f) { //根据参数进行位置插值计算 p.pos = Vector3.Lerp(p.pos, p.src.position, FixFactor(p.pfactor)); p.dst.position = p.pos; var src_parent = p.src.parent; var dst_parent = p.dst.parent; if (src_parent != null && dst_parent != null) { //计算当前位置与父的位置距离 var src_dis = Vector3.Distance(src_parent.position, p.src.position); var dst_dis = Vector3.Distance(dst_parent.position, p.dst.position); if (src_dis != 0 && dst_dis != 0) { //计算目标位置相对父位置的方向,并根据方向重新计算目标的位置 var dst_dir = Vector3.Normalize(p.dst.position - dst_parent.position); p.dst.position = dst_parent.position + dst_dir * (src_dis * 0.4f + dst_dis * 0.6f); } } } else { p.dst.position = p.src.position; } //对旋转信息进行插值计算 p.rot = Quaternion.Slerp(p.rot, p.src.rotation, FixFactor(p.rfactor)); p.dst.rotation = p.rot; } } } #endregion #region//公共接口 //恢复原始位置 public void ResetPose() { if (m_particles != null) { for (int i = 0; i < m_particles.Length; ++i) { var p = m_particles[i]; p.pos = p.dst.position; p.rot = p.dst.rotation; p.src.position = p.pos; p.src.rotation = p.rot; } } } //进行恢复处理 public void DoReset() { m_particles = null; if (m_srcRoot != null && m_dstRoot != null) { var particles = new List(); UnityHierarchyUtils.WalkHierarchy( m_srcRoot, t => { if (t.name.StartsWith("weiba", StringComparison.CurrentCultureIgnoreCase)) { var p = new Particle(); p.src = t; var root = m_srcRoot; if (root != t) { var h = UnityUtils.GetTransPathFrom(t, root); var depth = UnityUtils.GetHierarchyDepthFrom(t, root); var a = Math.Min(depth, depth_pfactors.Length - 1); var b = Math.Min(depth, depth_rfactors.Length - 1); p.dst = m_dstRoot.Find(h); p.pfactor = depth_pfactors[a]; p.rfactor = depth_rfactors[b]; } else { p.dst = m_dstRoot; p.pfactor = 1.0f; p.rfactor = 1.0f; } if (p.dst != null) { t.position = p.dst.position; t.rotation = p.dst.rotation; p.pos = t.position; p.rot = t.rotation; particles.Add(p); } } return true; } ); m_particles = particles.ToArray(); } } #endregion #region//私有函数 private void OnTransformParentChanged() { m_parentChanged = true; } #endregion #region//静态函数与方法 //位置参数--层次越深跟随的参数就越小 private static float[] depth_pfactors = new float[] { 1.0f, 0.5f, 0.3f, 0.2f, }; //旋转参数--层次越深跟随的参数就越小 private static float[] depth_rfactors = new float[] { 1.0f, 0.75f, 0.2f, 0.1f, }; //基础参数 private static float BaseFactor = 45; //根据时间进行参数修正 private static float FixFactor(float factor) { #if UNITY_EDITOR if (Application.isPlaying) { return factor * Time.deltaTime * BaseFactor; } else { return factor; } #else return factor * Time.deltaTime * BaseFactor; #endif } #endregion #region//子类定义 /// /// 每一个部分 /// [Serializable] public class Particle { public Transform src = null; public Transform dst = null; public Vector3 pos = Vector3.zero; public Quaternion rot = Quaternion.identity; [Range(0.1f, 1.0f)] public float pfactor = 0.1f; [Range(0.1f, 1.0f)] public float rfactor = 0.1f; } #endregion }