void AnalyzeStateMachine(UnityEditor.Animations.AnimatorStateMachine stateMachine, Animator animator, SkinnedMeshRenderer[] meshRender, int layer, int bakeFPS, int animationIndex) { AnimationInstancing instance = generatedPrefab.GetComponent <AnimationInstancing>(); if (instance == null) { Debug.LogError("You should select a prefab with AnimationInstancing component."); return; } if (string.IsNullOrEmpty(instance.cfgName)) { instance.cfgName = generatedPrefab.name; } for (int i = 0; i != stateMachine.states.Length; ++i) { ChildAnimatorState state = stateMachine.states[i]; if (state.state == null || state.state.motion == null) // add by chenbin { continue; // add by chenbin } // add by chenbin bool needBake = false; if (!generateAnims.TryGetValue(state.state.motion.name, out needBake)) { continue; } foreach (var obj in generateInfo) { if (obj.info.animationName == state.state.motion.name) { needBake = false; break; } } if (!needBake) { continue; } AnimationBakeInfo bake = new AnimationBakeInfo(); bake.length = state.state.motion.averageDuration; bake.animator = animator; bake.animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; bake.meshRender = meshRender; bake.layer = layer; bake.info = new AnimationInfo(); bake.info.animationName = state.state.motion.name; bake.info.animationNameHash = state.state.nameHash; bake.info.animationIndex = animationIndex; bake.info.totalFrame = (int)(state.state.motion.averageDuration * bakeFPS); bake.info.fps = bakeFPS; bake.info.rootMotion = true; if (bake.info.rootMotion) { bake.info.velocity = new Vector3[bake.info.totalFrame]; bake.info.angularVelocity = new Vector3[bake.info.totalFrame]; } generateInfo.Add(bake); animationIndex += bake.info.totalFrame; totalFrame += bake.info.totalFrame; bake.info.eventList = new List <AnimationEvent>(); AnimationClip clip = state.state.motion as AnimationClip; foreach (var evt in clip.events) { AnimationEvent aniEvent = new AnimationEvent(); aniEvent.function = evt.functionName; aniEvent.floatParameter = evt.floatParameter; aniEvent.intParameter = evt.intParameter; aniEvent.stringParameter = evt.stringParameter; aniEvent.time = evt.time; if (evt.objectReferenceParameter != null) { aniEvent.objectParameter = evt.objectReferenceParameter.name; } else { aniEvent.objectParameter = ""; } bake.info.eventList.Add(aniEvent); } cacheTransition.Add(state.state, state.state.transitions); state.state.transitions = null; cacheAnimationEvent.Add(clip, clip.events); UnityEngine.AnimationEvent[] tempEvent = new UnityEngine.AnimationEvent[0]; UnityEditor.AnimationUtility.SetAnimationEvents(clip, tempEvent); } for (int i = 0; i != stateMachine.stateMachines.Length; ++i) { AnalyzeStateMachine(stateMachine.stateMachines[i].stateMachine, animator, meshRender, layer, bakeFPS, animationIndex); } }
void GenerateAnimation() { if (generateInfo.Count > 0 && workingInfo == null) { workingInfo = generateInfo[0]; generateInfo.RemoveAt(0); workingInfo.animator.gameObject.SetActive(true); workingInfo.animator.Play(workingInfo.info.animationNameHash); workingInfo.workingFrame = 0; workingInfo.animator.Update(workingInfo.length / workingInfo.info.totalFrame); return; } if (workingInfo != null) { workingInfo.info.velocity[workingInfo.workingFrame] = workingInfo.animator.velocity; workingInfo.info.angularVelocity[workingInfo.workingFrame] = workingInfo.animator.angularVelocity * Mathf.Rad2Deg; float deltaTime = workingInfo.length / workingInfo.info.totalFrame; workingInfo.animator.Update(deltaTime); for (int j = 0; j != workingInfo.meshRender.Length; ++j) { GenerateBoneMatrix(workingInfo.meshRender[j].name.GetHashCode(), workingInfo.info.animationNameHash, workingInfo.workingFrame, Matrix4x4.identity, false); } EditorUtility.DisplayProgressBar("Generating Animations", string.Format("Animation '{0}' is Generating.", workingInfo.info.animationName), ((float)(generateCount - generateInfo.Count) / generateCount)); //Debug.Log(string.Format("Animation '{0}' is Generating. Current frame is {1}", workingInfo.info.animationName, workingInfo.workingFrame)); if (++workingInfo.workingFrame >= workingInfo.info.totalFrame) { aniInfo.Add(workingInfo.info); if (generateInfo.Count == 0) { foreach (var obj in cacheTransition) { obj.Key.transitions = obj.Value; } cacheTransition.Clear(); foreach (var obj in cacheAnimationEvent) { UnityEditor.AnimationUtility.SetAnimationEvents(obj.Key, obj.Value); } cacheAnimationEvent.Clear(); PrepareBoneTexture(aniInfo); SetupAnimationTexture(aniInfo); SaveAnimationInfo(generatedPrefab.name); DestroyImmediate(workingInfo.animator.gameObject); EditorUtility.ClearProgressBar(); } if (workingInfo.animator != null) { workingInfo.animator.gameObject.transform.position = Vector3.zero; workingInfo.animator.gameObject.transform.rotation = Quaternion.identity; } workingInfo = null; } } }
void AnalyzeStateMachine(AnimationLayerInfo pLayerInfo, UnityEditor.Animations.AnimatorControllerLayer ownerLayer, UnityEditor.Animations.AnimatorStateMachine stateMachine, Animator animator, SkinnedMeshRenderer[] meshRender, int layer, int bakeFPS, int animationIndex) { var tmachineInfo = new AnimationStateMachineInfo() { layerIndex = pLayerInfo.index, index = pLayerInfo.machines.Count, defaultName = stateMachine.defaultState != null ? stateMachine.defaultState.name : "", machineName = stateMachine.name }; pLayerInfo.machines.Add(tmachineInfo); for (int i = 0; i != stateMachine.states.Length; ++i) { ChildAnimatorState state = stateMachine.states[i]; var tstateinfo = new AnimationStateInfo() { layerIndex = pLayerInfo.index, machineIndex = tmachineInfo.index, index = i }; tstateinfo.SetData(state.state); tmachineInfo.stateInfos.Add(tstateinfo); AnimationClip clip = state.state.motion as AnimationClip; bool needBake = false; if (clip == null) { continue; } if (!generateAnims.TryGetValue(clip.name, out needBake)) { continue; } foreach (var obj in generateInfo) { if (obj.info.animationName == clip.name) { needBake = false; break; } } if (!needBake) { continue; } AnimationBakeInfo bake = new AnimationBakeInfo(); bake.length = clip.averageDuration; bake.animator = animator; bake.animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; bake.meshRender = meshRender; bake.layer = layer; bake.info = new AnimationInfo(); bake.info.animationName = clip.name; bake.info.animationNameHash = state.state.nameHash; bake.info.animationIndex = animationIndex; bake.info.totalFrame = (int)(bake.length * bakeFPS + 0.5f) + 1; bake.info.totalFrame = Mathf.Clamp(bake.info.totalFrame, 1, bake.info.totalFrame); bake.info.fps = bakeFPS; bake.info.rootMotion = true; bake.info.wrapMode = clip.isLooping ? WrapMode.Loop : clip.wrapMode; if (bake.info.rootMotion) { bake.info.velocity = new Vector3[bake.info.totalFrame]; bake.info.angularVelocity = new Vector3[bake.info.totalFrame]; } generateInfo.Add(bake); animationIndex += bake.info.totalFrame; totalFrame += bake.info.totalFrame; bake.info.eventList = new List <AnimationEvent>(); //AnimationClip clip = state.state.motion as AnimationClip; foreach (var evt in clip.events) { AnimationEvent aniEvent = new AnimationEvent(); aniEvent.function = evt.functionName; aniEvent.floatParameter = evt.floatParameter; aniEvent.intParameter = evt.intParameter; aniEvent.stringParameter = evt.stringParameter; aniEvent.time = evt.time; if (evt.objectReferenceParameter != null) { aniEvent.objectParameter = evt.objectReferenceParameter.name; } else { aniEvent.objectParameter = ""; } bake.info.eventList.Add(aniEvent); } cacheTransition.Add(state.state, state.state.transitions); state.state.transitions = null; cacheAnimationEvent.Add(clip, clip.events); UnityEngine.AnimationEvent[] tempEvent = new UnityEngine.AnimationEvent[0]; UnityEditor.AnimationUtility.SetAnimationEvents(clip, tempEvent); } for (int i = 0; i != stateMachine.stateMachines.Length; ++i) { AnalyzeStateMachine(pLayerInfo, ownerLayer, stateMachine.stateMachines[i].stateMachine, animator, meshRender, layer, bakeFPS, animationIndex); } }
private void SaveAnimationInfo(string name, AnimationBakeInfo pWorkInfo) { string path = GetFilePath(); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } UnityEditor.Animations.AnimatorController controller = pWorkInfo.animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController; //AssetDatabase.CreateFolder("Assets/Resources", folderName); FileStream file = File.Open(GetFullPahtFile(name), FileMode.Create); BinaryWriter writer = new BinaryWriter(file); //存储参数 int tpamCount = controller.parameters != null ? controller.parameters.Length : 0; writer.Write(tpamCount); if (controller.parameters != null && controller.parameters.Length > 0) { AssetParameter.Parameter[] tparms = new AssetParameter.Parameter[tpamCount]; for (int i = 0; i < tpamCount; i++) { AssetParameter.Parameter tpamdata = new AssetParameter.Parameter(); tpamdata.CopyData(controller.parameters[i]); tpamdata.WriteToFile(writer); } } writer.Write(layerInfos.Count); foreach (var item in layerInfos) { item.WriteToFile(writer); } //存储animation State writer.Write(aniInfo.Count); foreach (var obj in aniInfo) { AnimationInfo info = (AnimationInfo)obj; //writer.Write(info.animationNameHash); writer.Write(info.animationName); writer.Write(info.animationIndex); writer.Write(info.textureIndex); writer.Write(info.totalFrame); writer.Write(info.fps); writer.Write(info.rootMotion); writer.Write((int)info.wrapMode); if (info.rootMotion) { Debug.Assert(info.totalFrame == info.velocity.Length); for (int i = 0; i != info.velocity.Length; ++i) { writer.Write(info.velocity[i].x); writer.Write(info.velocity[i].y); writer.Write(info.velocity[i].z); writer.Write(info.angularVelocity[i].x); writer.Write(info.angularVelocity[i].y); writer.Write(info.angularVelocity[i].z); } } writer.Write(info.eventList.Count); foreach (var evt in info.eventList) { writer.Write(evt.function); writer.Write(evt.floatParameter); writer.Write(evt.intParameter); writer.Write(evt.stringParameter); writer.Write(evt.time); writer.Write(evt.objectParameter); } } //attach writer.Write(exposeAttachments); if (exposeAttachments) { writer.Write(extraBoneInfo.extraBone.Length); for (int i = 0; i != extraBoneInfo.extraBone.Length; ++i) { writer.Write(extraBoneInfo.extraBone[i]); } for (int i = 0; i != extraBoneInfo.extraBindPose.Length; ++i) { for (int j = 0; j != 16; ++j) { writer.Write(extraBoneInfo.extraBindPose[i][j]); } } } //boneTexture Texture2D[] texture = bakedBoneTexture; writer.Write(texture.Length); writer.Write(textureBlockWidth); writer.Write(textureBlockHeight); for (int i = 0; i != texture.Length; ++i) { byte[] bytes = texture[i].GetRawTextureData(); writer.Write(texture[i].width); writer.Write(texture[i].height); writer.Write(bytes.Length); writer.Write(bytes); } file.Close(); aniInfo.Clear(); }
void GenerateAnimation() { if (generateInfo.Count > 0 && workingInfo == null) { workingInfo = generateInfo[0]; generateInfo.RemoveAt(0); workingInfo.animator.gameObject.SetActive(true); workingInfo.animator.Update(0); workingInfo.animator.Play(workingInfo.info.animationNameHash); workingInfo.animator.Update(0); workingInfo.workingFrame = 0; return; } if (workingInfo != null) { //float time = workingInfo.animator.GetCurrentAnimatorStateInfo(0).normalizedTime; //Debug.Log("The time is" + time); for (int j = 0; j != workingInfo.meshRender.Length; ++j) { GenerateBoneMatrix(workingInfo.meshRender[j].name.GetHashCode(), workingInfo.info.animationNameHash, workingInfo.workingFrame, Matrix4x4.identity, false); } //Debug.Log("The length is" + workingInfo.animator.velocity.magnitude); workingInfo.info.velocity[workingInfo.workingFrame] = workingInfo.animator.velocity; workingInfo.info.angularVelocity[workingInfo.workingFrame] = workingInfo.animator.angularVelocity * Mathf.Rad2Deg; EditorUtility.DisplayProgressBar("Brake Animation" + workingInfo.info.animationName, string.Format("curFrame {0}", workingInfo.workingFrame), (float)workingInfo.workingFrame / workingInfo.info.totalFrame); if (++workingInfo.workingFrame >= workingInfo.info.totalFrame) { aniInfo.Add(workingInfo.info); if (generateInfo.Count == 0) { foreach (var obj in cacheTransition) { obj.Key.transitions = obj.Value; } cacheTransition.Clear(); foreach (var obj in cacheAnimationEvent) { UnityEditor.AnimationUtility.SetAnimationEvents(obj.Key, obj.Value); } cacheAnimationEvent.Clear(); try { PrepareBoneTexture(aniInfo); SetupAnimationTexture(aniInfo); SaveAnimationInfo(generatedScript.aniFilename, workingInfo); Debug.Log("Complete !!!!"); } catch (System.Exception erro) { Debug.LogError(erro); } DestroyImmediate(workingInfo.animator.gameObject); EditorUtility.ClearProgressBar(); AssetDatabase.Refresh(); } if (workingInfo.animator != null) { workingInfo.animator.gameObject.transform.position = Vector3.zero; workingInfo.animator.gameObject.transform.rotation = Quaternion.identity; } workingInfo = null; return; } float deltaTime = workingInfo.length / (workingInfo.info.totalFrame - 1); workingInfo.animator.Update(deltaTime); } }