public void Prepare(AnimationInfo[] pinfos, ExtraBoneInfo extraBoneInfo) { //extraBoneInfo = extraBoneInfo; List <Matrix4x4> bindPose = new List <Matrix4x4>(150); // to optimize, MergeBone don't need to call every time Transform[] bones = RuntimeHelper.MergeBone(lodInfo[0].skinnedMeshRenderer, bindPose); allTransforms = bones; if (extraBoneInfo != null) { List <Transform> list = new List <Transform>(); list.AddRange(bones); Transform[] transforms = gameObject.GetComponentsInChildren <Transform>(); for (int i = 0; i != extraBoneInfo.extraBone.Length; ++i) { for (int j = 0; j != transforms.Length; ++j) { if (extraBoneInfo.extraBone[i] == transforms[j].name) { list.Add(transforms[j]); } } bindPose.Add(extraBoneInfo.extraBindPose[i]); } allTransforms = list.ToArray(); } AnimationInstancingMgr.Instance.AddMeshVertex(aniFilename, lodInfo, allTransforms, bindPose, bonePerVertex); foreach (var lod in lodInfo) { foreach (var cache in lod.vertexCacheList) { cache.shadowcastingMode = shadowCastingMode; cache.receiveShadow = receiveShadow; cache.layer = layer; } } Destroy(GetComponent <Animator>()); }
void BakeWithAnimator() { if (generatedPrefab != null) { generatedObject = Instantiate(generatedPrefab); Selection.activeGameObject = generatedObject; generatedObject.transform.position = Vector3.zero; generatedObject.transform.rotation = Quaternion.identity; Animator animator = generatedObject.GetComponentInChildren <Animator>(); AnimationInstancing script = generatedObject.GetComponent <AnimationInstancing>(); Debug.Assert(script); SkinnedMeshRenderer[] meshRender = generatedObject.GetComponentsInChildren <SkinnedMeshRenderer>(); List <Matrix4x4> bindPose = new List <Matrix4x4>(150); Transform[] boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose); // calculate the bindpose of attached points if (generatedFbx) { List <Transform> listExtra = new List <Transform>(); Transform[] trans = generatedFbx.GetComponentsInChildren <Transform>(); Transform[] bakedTrans = generatedObject.GetComponentsInChildren <Transform>(); foreach (var obj in selectExtraBone) { if (!obj.Value) { continue; } for (int i = 0; i != trans.Length; ++i) { Transform tran = trans[i] as Transform; if (tran.name == obj.Key) { bindPose.Add(tran.localToWorldMatrix); listExtra.Add(bakedTrans[i]); } } } Transform[] totalTransform = new Transform[boneTransform.Length + listExtra.Count]; System.Array.Copy(boneTransform, totalTransform, boneTransform.Length); System.Array.Copy(listExtra.ToArray(), 0, totalTransform, boneTransform.Length, listExtra.Count); boneTransform = totalTransform; //boneTransform = boneTransform; extraBoneInfo = new ExtraBoneInfo(); extraBoneInfo.extraBone = new string[listExtra.Count]; extraBoneInfo.extraBindPose = new Matrix4x4[listExtra.Count]; for (int i = 0; i != listExtra.Count; ++i) { extraBoneInfo.extraBone[i] = listExtra[i].name; extraBoneInfo.extraBindPose[i] = bindPose[bindPose.Count - listExtra.Count + i]; } } Reset(); AddMeshVertex2Generate(meshRender, boneTransform, bindPose.ToArray()); Transform rootNode = meshRender[0].rootBone; for (int j = 0; j != meshRender.Length; ++j) { meshRender[j].enabled = true; } animator.applyRootMotion = true; totalFrame = 0; //初始化数据 cacheTransition.Clear(); cacheAnimationEvent.Clear(); layerInfos.Clear(); AnimationInstancing instance = generatedPrefab.GetComponent <AnimationInstancing>(); if (instance == null) { Debug.LogError("You should select a prefab with AnimationInstancing component."); return; } SetFileName(generatedPrefab); var controller = animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController; var tlayers = controller.layers; for (int i = 0; i < tlayers.Length; i++) { var layer = tlayers[i]; var tinfo = new AnimationLayerInfo() { name = layer.name, index = i }; AnalyzeStateMachine(tinfo, layer, layer.stateMachine, animator, meshRender, 0, aniFps, 0); layerInfos.Add(tinfo); } // UnityEditor.Animations.AnimatorControllerLayer layer = controller.layers[0]; //AnalyzeStateMachine(layer.stateMachine, animator, meshRender, 0, aniFps, 0); generateCount = generateInfo.Count; } }
private void OnGUI() { GUI.skin.label.richText = true; GUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); GameObject prefab = EditorGUILayout.ObjectField("Asset to Generate", generatedPrefab, typeof(GameObject), true) as GameObject; if (prefab != generatedPrefab) { generateAnims.Clear(); customClips.Clear(); generatedPrefab = prefab; SetFileName(generatedPrefab); generatedScript = generatedPrefab?.GetComponent <AnimationInstancing>(); SkinnedMeshRenderer[] meshRender = generatedPrefab.GetComponentsInChildren <SkinnedMeshRenderer>(); List <Matrix4x4> bindPose = new List <Matrix4x4>(150); boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose); } if (generatedPrefab == null) { EditorGUILayout.LabelField("Error: the object is null"); return; } if (generatedScript != null) { generatedScript.aniFilename = EditorGUILayout.TextField("aniFilename", generatedScript.aniFilename); } else { EditorGUILayout.LabelField("Error: the object is not have AnimationInstancing"); return; } bool error = false; if (generatedPrefab) { exposeAttachments = EditorGUILayout.Toggle("Enable Attachments", exposeAttachments); if (exposeAttachments) { showAttachmentSetting = EditorGUILayout.Foldout(showAttachmentSetting, "Attachment setting"); if (showAttachmentSetting) { EditorGUI.BeginChangeCheck(); GameObject fbx = EditorGUILayout.ObjectField("FBX refrenced by Prefab:", generatedFbx, typeof(GameObject), false) as GameObject; if (EditorGUI.EndChangeCheck()) { if (fbx != generatedFbx) { SkinnedMeshRenderer[] meshRender = generatedPrefab.GetComponentsInChildren <SkinnedMeshRenderer>(); List <Matrix4x4> bindPose = new List <Matrix4x4>(150); boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose); generatedFbx = fbx; var allTrans = generatedPrefab.GetComponentsInChildren <Transform>().ToList(); allTrans.RemoveAll(q => boneTransform.Contains(q)); //var allTrans = boneTransform; selectExtraBone.Clear(); for (int i = 0; i != allTrans.Count; ++i) { selectExtraBone.Add(allTrans[i].name, false); } } else if (fbx == null) { selectExtraBone.Clear(); } } if (selectExtraBone.Count > 0) { var temp = new Dictionary <string, bool>(); foreach (var obj in selectExtraBone) { temp[obj.Key] = obj.Value; } scrollPosition2 = GUILayout.BeginScrollView(scrollPosition2); foreach (var obj in temp) { bool value = EditorGUILayout.Toggle(string.Format(" {0}", obj.Key), obj.Value); selectExtraBone[obj.Key] = value; } GUILayout.EndScrollView(); } } } else { generatedFbx = null; } aniFps = EditorGUILayout.IntSlider("FPS", aniFps, 1, 120); Animator animator = generatedPrefab.GetComponentInChildren <Animator>(); if (animator == null) { EditorGUILayout.LabelField("Error: The prefab should have a Animator Component."); return; } if (animator.runtimeAnimatorController == null) { EditorGUILayout.LabelField("Error: The prefab's Animator should have a Animator Controller."); return; } var clips = GetClips(animator); string[] clipNames = generateAnims.Keys.ToArray(); int totalFrames = 0; List <int> frames = new List <int>(); foreach (var clipName in clipNames) { if (!generateAnims[clipName]) { continue; } AnimationClip clip = clips.Find(delegate(AnimationClip c) { if (c != null) { return(c.name == clipName); } return(false); }); int framesToBake = clip ? (int)(clip.length * aniFps / 1.0f) : 1; framesToBake = Mathf.Clamp(framesToBake, 1, framesToBake); totalFrames += framesToBake; frames.Add(framesToBake); } int textureCount = 1; int textureWidth = CalculateTextureSize(out textureCount, frames.ToArray(), boneTransform); error = textureCount == 0; if (textureCount == 0) { EditorGUILayout.LabelField("Error: There is certain animation's frames which is larger than a whole texture."); } else if (textureCount == 1) { EditorGUILayout.LabelField(string.Format("Animation Texture will be one {0} X {1} texture", textureWidth, textureWidth)); } else { EditorGUILayout.LabelField(string.Format("Animation Texture will be {2} 1024 X 1024 and one {0} X {1} textures", textureWidth, textureWidth, textureCount - 1)); } scrollPosition = GUILayout.BeginScrollView(scrollPosition); foreach (var clipName in clipNames) { AnimationClip clip = clips.Find(delegate(AnimationClip c) { if (c != null) { return(c.name == clipName); } return(false); }); int framesToBake = clip ? (int)(clip.length * aniFps / 1.0f) : 1; framesToBake = Mathf.Clamp(framesToBake, 1, framesToBake); GUILayout.BeginHorizontal(); { generateAnims[clipName] = EditorGUILayout.Toggle(string.Format("({0}) {1} ", framesToBake, clipName), generateAnims[clipName]); GUI.enabled = generateAnims[clipName]; //frameSkips[clipName] = Mathf.Clamp(EditorGUILayout.IntField(frameSkips[clipName]), 1, fps); GUI.enabled = true; } GUILayout.EndHorizontal(); if (framesToBake > 5000) { GUI.skin.label.richText = true; EditorGUILayout.LabelField("<color=red>Long animations degrade performance, consider using a higher frame skip value.</color>", GUI.skin.label); } } GUILayout.EndScrollView(); } if (generatedPrefab && !error) { if (GUILayout.Button(string.Format("Generate"))) { if (string.IsNullOrEmpty(generatedScript.aniFilename)) { if (EditorUtility.DisplayDialog("Setting FileName for Animation ", string.Format("Set AniFileName To {0} ?.", generatedPrefab.name), "Set ", "cancel")) { SetFileName(generatedPrefab); } else { return; } } string tfile = GetFullPahtFile(generatedScript.aniFilename); if (File.Exists(tfile)) { if (EditorUtility.DisplayDialog("Export To Animation", string.Format("{0} is already in path {1}.", generatedScript.aniFilename, tfile), "OverWrite", "cancel")) { BakeWithAnimator(); } } else { BakeWithAnimator(); } } } }