private void DeoptimizeTransformHierarchy() { if (avatar == null) { throw new Exception("Transform hierarchy has been optimized, but can't find Avatar to deoptimize."); } // 1. Figure out the skeletonPaths from the unstripped avatar var skeletonPaths = new List <string>(); foreach (var id in avatar.m_Avatar.m_AvatarSkeleton.m_ID) { var path = avatar.FindBonePath(id); skeletonPaths.Add(path); } // 2. Restore the original transform hierarchy // Prerequisite: skeletonPaths follow pre-order traversal for (var i = 1; i < skeletonPaths.Count; i++) // start from 1, skip the root transform because it will always be there. { var path = skeletonPaths[i]; var strs = path.Split('/'); string transformName; ImportedFrame parentFrame; if (strs.Length == 1) { transformName = path; parentFrame = RootFrame; } else { transformName = strs.Last(); var parentFramePath = path.Substring(0, path.LastIndexOf('/')); parentFrame = RootFrame.FindRelativeFrameWithPath(parentFramePath); } var skeletonPose = avatar.m_Avatar.m_DefaultPose; var xform = skeletonPose.m_X[i]; var frame = RootFrame.FindChild(transformName); if (frame != null) { SetFrame(frame, xform.t, xform.q, xform.s); } else { frame = CreateFrame(transformName, xform.t, xform.q, xform.s); } parentFrame.AddChild(frame); } }