private static BoneSampleData GetBoneSampleDataRecursive(Transform node, List <Transform> smrBones, string basePath, List <BoneSampleData> result, short boneIdx)
        {
            // 如果此节点及其所有子节点都不在 SkinnedMeshRenderer 内则忽略(此类节点可能是挂点,由 Joint 控制)
            if (!IsNodeIsBone(node, smrBones))
            {
                return(null);
            }

            BoneSampleData boneInfo = new BoneSampleData();

            boneInfo.transform = node;
            boneInfo.path      = (basePath == string.Empty) ? node.name : string.Format("{0}/{1}", basePath, node.name);
            boneInfo.boneIdx   = boneIdx;

            result.Add(boneInfo);

            int childrenCount = node.childCount;

            for (int i = 0; i < childrenCount; i++)
            {
                Transform      child     = node.GetChild(i);
                BoneSampleData childBone = GetBoneSampleDataRecursive(child, smrBones, boneInfo.path, result, boneIdx++);
                if (childBone != null)
                {
                    childBone.parent = node;
                }
            }

            return(boneInfo);
        }
        /// <summary>
        /// 获取节点及其所有子节点的骨骼数据并设置其parent关系(深度优先), 同时记录绑点信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="boneRoot"></param>
        /// <param name="basePath"></param>
        /// <param name="result"></param>
        public static void GetBoneSampleDataRecursive(GameObject obj, Transform boneRoot, string basePath, Transform[] jointNodes, List <BoneSampleData> result)
        {
            List <Transform> smrBones = GetAllSmrBones(obj);

            GetBoneSampleDataRecursive(boneRoot, smrBones, basePath, result, 0);
            foreach (var joint in jointNodes)
            {
                bool found = false;
                foreach (var bone in result)
                {
                    if (bone.transform == joint)
                    {
                        bone.isJoint = true;
                        bone.exposed = true;
                        found        = true;
                        break;
                    }
                }

                if (!found) // 纯绑点,不属于 bone
                {
                    List <Transform> parents  = new List <Transform>();
                    Transform        currNode = joint;
                    while (currNode != obj.transform)
                    {
                        parents.Insert(0, currNode);
                        currNode = currNode.parent;
                    }

                    string path = string.Empty;
                    for (int i = 0; i < parents.Count; i++)
                    {
                        Transform jointNode = parents[i];
                        path += jointNode.name + "/";
                        var boneFinded = from boneNode in result where boneNode.transform == jointNode select boneNode.transform;
                        if (boneFinded != null) // 这个路径节点是骨骼
                        {
                            continue;
                        }

                        BoneSampleData data = new BoneSampleData();
                        data.transform   = jointNode;
                        data.parent      = i == 0 ? null : parents[i - 1];
                        data.path        = jointNode.name;
                        data.boneIdx     = -1;
                        data.isJoint     = true;
                        data.isPureJoint = true;
                        data.exposed     = i == parents.Count - 1;
                        data.bindPose    = Matrix4x4.TRS(jointNode.localPosition, jointNode.localRotation, jointNode.localScale);
                    }
                }
            }
        }