//============================================================================================ /** * @brief * *********************************************************************************************/ public FootStepTagTrack(FootStepTagTrack a_copy) : base(a_copy) { for(int i=0; i < a_copy.m_footStepData.Count; ++i) { m_footStepData.Add(a_copy.m_footStepData[i]); } }
public void ScrapGeneratedClips() { if (GeneratedClip != null) { AssetDatabase.RemoveObjectFromAsset(GeneratedClip); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(this)); GeneratedClip = null; } GeneratedTagTracks = new List<TagTrack>(); GeneratedEvents = new List<EventMarker>(); GeneratedUserBoolTracks = new List<TagTrackBase>(); if (PrimaryClip != null) { GeneratedLeftFootStepTrack = new FootStepTagTrack(0, "FootStep Left", PrimaryClip.length); GeneratedRightFootStepTrack = new FootStepTagTrack(1, "FootStep Right", PrimaryClip.length); GeneratedWarpPositionTrack = new TagTrackBase(2, "Diable Warp (Position)", PrimaryClip.length); GeneratedWarpRotationTrack = new TagTrackBase(3, "Disable Warp (Rotation)", PrimaryClip.length); GeneratedEnableRootMotionTrack = new TagTrackBase(4, "Disable Matching", PrimaryClip.length); GeneratedPoseFavourTrack = new FloatTagTrack(5, "Pose Favour", PrimaryClip.length); GeneratedWarpTrajLatTrack = new TagTrackBase(6, "Disable Trajectory Warp (Angular)", PrimaryClip.length); GeneratedWarpTrajLongTrack = new TagTrackBase(7, "Disable Trajectory Warp (Long)", PrimaryClip.length); GeneratedPoseFavourTrack.DefaultValue = PoseFavourTrack.DefaultValue; } }
public void ValidateBaseData() { if (MotionModifier == null) MotionModifier = new MotionModifyData(); if (Events == null) Events = new List<EventMarker>(); if (TagTracks == null) TagTracks = new List<TagTrack>(); if (FavourTagTracks == null) FavourTagTracks = new List<TagTrack>(); if (GeneratedEvents == null) GeneratedEvents = new List<EventMarker>(); if (GeneratedTagTracks == null) GeneratedTagTracks = new List<TagTrack>(); if (GeneratedFavourTagTracks == null) GeneratedFavourTagTracks = new List<TagTrack>(); if (GeneratedUserBoolTracks == null) GeneratedUserBoolTracks = new List<TagTrackBase>(); if (PrimaryClip != null) { if (LeftFootStepTrack == null || LeftFootStepTrack.Name == null || LeftFootStepTrack.Name == "") LeftFootStepTrack = new FootStepTagTrack(0, "Footstep Left", PrimaryClip.length); if (RightFootStepTrack == null || RightFootStepTrack.Name == null || RightFootStepTrack.Name == "") RightFootStepTrack = new FootStepTagTrack(1, "Footstep Right", PrimaryClip.length); if (WarpPositionTrack == null || WarpPositionTrack.Name == null || WarpPositionTrack.Name == "") WarpPositionTrack = new TagTrackBase(2, "Disable Warp (Position)", PrimaryClip.length); if (WarpRotationTrack == null || WarpRotationTrack.Name == null || WarpRotationTrack.Name == "") WarpRotationTrack = new TagTrackBase(3, "Disable Warp (Rotation)", PrimaryClip.length); if (EnableRootMotionTrack == null || EnableRootMotionTrack.Name == null || EnableRootMotionTrack.Name != "Disable Matching") EnableRootMotionTrack = new TagTrackBase(4, "Disable Matching", PrimaryClip.length); if (PoseFavourTrack == null || PoseFavourTrack.Name == null || PoseFavourTrack.Name == "" ) PoseFavourTrack = new FloatTagTrack(5, "Pose Favour", PrimaryClip.length); if (WarpTrajLatTrack == null || WarpTrajLatTrack.Name == null || WarpTrajLatTrack.Name == "") WarpTrajLatTrack = new TagTrackBase(6, "Disable Trajectory Warp (Angular)", PrimaryClip.length); if (WarpTrajLongTrack == null || WarpTrajLongTrack.Name == null || WarpTrajLongTrack.Name == "") WarpTrajLongTrack = new TagTrackBase(7, "Disable Trajectory Warp (Long)", PrimaryClip.length); PoseFavourTrack.DefaultValue = 1f; } MotionModifier.OnEnable(this); EditorUtility.SetDirty(this); }
public void ValidateBaseData() { if (MotionModifier == null) MotionModifier = new MotionModifyData(); if (TagTracks == null) TagTracks = new List<TagTrack>(); if (FavourTagTracks == null) FavourTagTracks = new List<TagTrack>(); if (GeneratedTagTracks == null) GeneratedTagTracks = new List<TagTrack>(); if (GeneratedFavourTagTracks == null) GeneratedFavourTagTracks = new List<TagTrack>(); if (m_clips == null) m_clips = new List<AnimationClip>(); if (m_positions == null) m_positions = new List<Vector2>(); if (m_clips != null && m_clips.Count > 0) { float clipLength = m_clips[0].length; if (LeftFootStepTrack == null || LeftFootStepTrack.Name == "" || LeftFootStepTrack.Name == null) LeftFootStepTrack = new FootStepTagTrack(0, "Footstep Left", clipLength); if (RightFootStepTrack == null || RightFootStepTrack.Name == "" || RightFootStepTrack.Name == null) RightFootStepTrack = new FootStepTagTrack(1, "Footstep Right", clipLength); if (WarpPositionTrack == null || WarpPositionTrack.Name == "" || WarpPositionTrack.Name == null) WarpPositionTrack = new TagTrackBase(2, "Disable Warp (Position)", clipLength); if (WarpRotationTrack == null || WarpRotationTrack.Name == "" || WarpRotationTrack.Name == null) WarpRotationTrack = new TagTrackBase(3, "Disable Warp (Rotation)", clipLength); if (EnableRootMotionTrack == null || EnableRootMotionTrack.Name == "" || EnableRootMotionTrack.Name == null) EnableRootMotionTrack = new TagTrackBase(4, "Enable Root Motion", clipLength); if (PoseFavourTrack == null || PoseFavourTrack.Name == "" || PoseFavourTrack.Name == null) PoseFavourTrack = new FloatTagTrack(5, "Pose Favour", clipLength); if (WarpTrajLatTrack == null || WarpTrajLatTrack.Name == null || WarpTrajLatTrack.Name == "") WarpTrajLatTrack = new TagTrackBase(6, "Disable Trajectory Warp (Angular)", clipLength); if (WarpTrajLongTrack == null || WarpTrajLongTrack.Name == null || WarpTrajLongTrack.Name == "") WarpTrajLongTrack = new TagTrackBase(7, "Disable Trajectory Warp (Long)", clipLength); PoseFavourTrack.SetDefaultTagValue(1f); } MotionModifier.OnEnable(this); EditorUtility.SetDirty(this); }
public void CopyData(MxMBlendSpace a_copy) { ValidateBaseData(); m_magnitude = a_copy.m_magnitude; m_smoothing = a_copy.m_smoothing; m_scatterSpace = a_copy.m_scatterSpace; m_scatterSpacing = a_copy.m_scatterSpacing; m_scatterPositions = null; UseSpeedMods = a_copy.UseSpeedMods; GlobalTags = a_copy.GlobalTags; GlobalFavourTags = a_copy.GlobalFavourTags; m_clips = new List<AnimationClip>(a_copy.m_clips); m_positions = new List<Vector2>(a_copy.Positions); if(m_targetPrefab == null) m_targetPrefab = a_copy.m_targetPrefab; TagTracks = new List<TagTrack>(a_copy.TagTracks.Count + 1); foreach(TagTrack track in a_copy.TagTracks) { TagTracks.Add(new TagTrack(track)); } FavourTagTracks = new List<TagTrack>(a_copy.FavourTagTracks.Count + 1); foreach(TagTrack track in a_copy.FavourTagTracks) { FavourTagTracks.Add(new TagTrack(track)); } UserBoolTracks = new List<TagTrackBase>(a_copy.UserBoolTracks.Count + 1); foreach(TagTrackBase track in a_copy.UserBoolTracks) { UserBoolTracks.Add(new TagTrackBase(track)); } LeftFootStepTrack = new FootStepTagTrack(a_copy.LeftFootStepTrack); RightFootStepTrack = new FootStepTagTrack(a_copy.RightFootStepTrack); WarpPositionTrack = new TagTrackBase(a_copy.WarpPositionTrack); WarpRotationTrack = new TagTrackBase(a_copy.WarpRotationTrack); EnableRootMotionTrack = new TagTrackBase(a_copy.EnableRootMotionTrack); PoseFavourTrack = new FloatTagTrack(a_copy.PoseFavourTrack); WarpTrajLatTrack = new TagTrackBase(a_copy.WarpTrajLatTrack); WarpTrajLongTrack = new TagTrackBase(a_copy.WarpTrajLongTrack); MotionModifier = new MotionModifyData(a_copy.MotionModifier, this); }
public void CopyTagsAndEvents(IMxMAnim a_target, bool a_mirrored) { //Copy Require tag tracks List<TagTrack> targetTagTracks = a_target.AnimTagTracks; if (targetTagTracks != null) { TagTracks = new List<TagTrack>(targetTagTracks.Count + 1); foreach (TagTrack track in targetTagTracks) { if (track != null) { TagTracks.Add(new TagTrack(track)); } } } //Copy Favour tag tracks List<TagTrack> targetFavourTracks = a_target.AnimFavourTagTracks; if (FavourTagTracks != null) { FavourTagTracks = new List<TagTrack>(targetFavourTracks.Count + 1); foreach (TagTrack track in targetFavourTracks) { if (track != null) FavourTagTracks.Add(new TagTrack(track)); } } //Copy User Tags List<TagTrackBase> userTagTracks = a_target.UserTagTracks; if (userTagTracks != null) { UserBoolTracks = new List<TagTrackBase>(userTagTracks.Count + 1); foreach (TagTrackBase track in userTagTracks) { if (track != null) UserBoolTracks.Add(track); } } //Copy Utility Tags List<TagTrackBase> utilityTagTracks = a_target.GenericTagTracks; if (utilityTagTracks != null) { if (a_mirrored) { if (utilityTagTracks.Count > 0) { RightFootStepTrack = new FootStepTagTrack(utilityTagTracks[0] as FootStepTagTrack); RightFootStepTrack.Name = "Footstep Right"; } if (utilityTagTracks.Count > 1) { LeftFootStepTrack = new FootStepTagTrack(utilityTagTracks[1] as FootStepTagTrack); LeftFootStepTrack.Name = "Footstep Left"; } } else { if (utilityTagTracks.Count > 0) LeftFootStepTrack = new FootStepTagTrack(utilityTagTracks[0] as FootStepTagTrack); if (utilityTagTracks.Count > 1) RightFootStepTrack = new FootStepTagTrack(utilityTagTracks[1] as FootStepTagTrack); } if (utilityTagTracks.Count > 2) WarpPositionTrack = new TagTrackBase(utilityTagTracks[2]); if (utilityTagTracks.Count > 3) WarpRotationTrack = new TagTrackBase(utilityTagTracks[3]); if (utilityTagTracks.Count > 4) EnableRootMotionTrack = new TagTrackBase(utilityTagTracks[4]); if (utilityTagTracks.Count > 5) PoseFavourTrack = new FloatTagTrack(utilityTagTracks[5] as FloatTagTrack); if (utilityTagTracks.Count > 6) WarpTrajLatTrack = new TagTrackBase(utilityTagTracks[6]); if (utilityTagTracks.Count > 7) WarpTrajLongTrack = new TagTrackBase(utilityTagTracks[7]); } }
public void GenerateModifiedAnimation(MxMPreProcessData a_preProcessData, string a_directory) { EditorUtility.DisplayProgressBar("Generate Modified Animation", "Scraping Old Anims", 0f); if (a_preProcessData != null) m_targetPreProcessData = a_preProcessData; ScrapGeneratedClips(); if (UseSpeedMods) { if (PrimaryClip != null && m_targetPreProcessData != null) { EditorUtility.DisplayProgressBar("Generate Modified Animation", "Copying Clip " + PrimaryClip.name, 0f); GeneratedClip = new AnimationClip(); EditorUtility.CopySerialized(PrimaryClip, GeneratedClip); GeneratedClip.name = PrimaryClip.name + "_MxM_MOD"; var curveBindings = AnimationUtility.GetCurveBindings(GeneratedClip); List<AnimationCurve> workingCurves = new List<AnimationCurve>(curveBindings.Length + 1); List<AnimationEvent> newEvents = new List<AnimationEvent>(); List<MotionSection> motionList = MotionModifier.MotionSections; MotionTimingPresets presets = m_targetPreProcessData.MotionTimingPresets; GeneratedTagTracks = new List<TagTrack>(TagTracks); GeneratedFavourTagTracks = new List<TagTrack>(TagTracks); GeneratedUserBoolTracks = new List<TagTrackBase>(UserBoolTracks); GeneratedLeftFootStepTrack = new FootStepTagTrack(LeftFootStepTrack); GeneratedRightFootStepTrack = new FootStepTagTrack(RightFootStepTrack); GeneratedWarpPositionTrack = new TagTrackBase(WarpPositionTrack); GeneratedWarpRotationTrack = new TagTrackBase(WarpRotationTrack); GeneratedEnableRootMotionTrack = new TagTrackBase(EnableRootMotionTrack); GeneratedPoseFavourTrack = new FloatTagTrack(PoseFavourTrack); GeneratedWarpTrajLatTrack = new TagTrackBase(WarpTrajLatTrack); GeneratedWarpTrajLongTrack = new TagTrackBase(WarpTrajLongTrack); //Create curves but don't add keys for (int i = 0; i < curveBindings.Length; ++i) { workingCurves.Add(new AnimationCurve()); } float cumTimeShift = 0f; //This is the cumulative amount of time shift at the point of modification; float curStartTime = 0f; //The start time for the current motion section int[] startKeyIndex = new int[workingCurves.Count]; //The start key for the current motion section for (int i = 0; i < motionList.Count; ++i) { EditorUtility.DisplayProgressBar("Generate Modified Animation", "Modifying Section " + i + " of " + PrimaryClip.name, ((float)i) / ((float)motionList.Count)); MotionSection motionSection = motionList[i]; float startWarpTime = curStartTime; float endWarpTime = motionSection.EndTime; float warpScale = motionSection.GetSpeedMod(curStartTime, presets, this); float localTimeShift = (endWarpTime - startWarpTime) - (endWarpTime - startWarpTime) * warpScale; //Shift Curve Keys for (int k = 0; k < curveBindings.Length; ++k) { EditorCurveBinding binding = curveBindings[k]; AnimationCurve originalCurve = AnimationUtility.GetEditorCurve(PrimaryClip, binding); AnimationCurve workingCurve = workingCurves[k]; //Make a cut at the end only int endKeyIndex = originalCurve.AddKey(endWarpTime, originalCurve.Evaluate(endWarpTime)); if (endKeyIndex == -1) endKeyIndex = originalCurve.keys.Length - 1; //Add in the intermediate keys scaled relative to the start and shifted by the cumulative time shift for (int keyIndex = startKeyIndex[k]; i < motionList.Count - 1 ? keyIndex < endKeyIndex : keyIndex <= endKeyIndex; ++keyIndex) { Keyframe key = originalCurve.keys[keyIndex]; key.time = startWarpTime + ((key.time - startWarpTime) * warpScale) - cumTimeShift; key.inTangent /= warpScale; key.outTangent /= warpScale; workingCurve.AddKey(key); } startKeyIndex[k] = endKeyIndex; } //Shift Events foreach (AnimationEvent evt in GeneratedClip.events) { if (evt.time > startWarpTime && evt.time < endWarpTime) { //Scale & Shift evt.time = startWarpTime + ((evt.time - startWarpTime) * warpScale) - cumTimeShift; } newEvents.Add(evt); } //Shift MxM Events foreach (EventMarker evt in Events) { EventMarker newMarker = new EventMarker(evt); if (newMarker.EventTime > startWarpTime && evt.EventTime < endWarpTime) { evt.EventTime = startWarpTime + ((evt.EventTime - startWarpTime) * warpScale) - cumTimeShift; } GeneratedEvents.Add(newMarker); } //Shift MXM Tag Points foreach (TagTrack track in GeneratedTagTracks) { List<Vector2> tagList = track.Tags; for (int k = 0; k < tagList.Count; ++k) { Vector2 newTag = tagList[k]; if (newTag.x > startWarpTime && newTag.x < endWarpTime) { newTag.x = startWarpTime + ((newTag.x - startWarpTime) * warpScale) - cumTimeShift; } if (newTag.y > startWarpTime && newTag.y < endWarpTime) { newTag.y = startWarpTime + ((newTag.y - startWarpTime) * warpScale) - cumTimeShift; } tagList[k] = newTag; } } //Shift MXM FavourTag Points foreach (TagTrack track in GeneratedFavourTagTracks) { List<Vector2> tagList = track.Tags; for (int k = 0; k < tagList.Count; ++k) { Vector2 newTag = tagList[k]; if (newTag.x > startWarpTime && newTag.x < endWarpTime) { newTag.x = startWarpTime + ((newTag.x - startWarpTime) * warpScale) - cumTimeShift; } if (newTag.y > startWarpTime && newTag.y < endWarpTime) { newTag.y = startWarpTime + ((newTag.y - startWarpTime) * warpScale) - cumTimeShift; } tagList[k] = newTag; } } //Shift MxM User Tags foreach (TagTrackBase track in GeneratedUserBoolTracks) { ShiftTrackTags(track, startWarpTime, endWarpTime, warpScale, cumTimeShift); } //Shift MxM Utility Tags ShiftTrackTags(GeneratedLeftFootStepTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); ShiftTrackTags(GeneratedRightFootStepTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); ShiftTrackTags(GeneratedWarpPositionTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); ShiftTrackTags(GeneratedWarpRotationTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); ShiftTrackTags(GeneratedEnableRootMotionTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); ShiftTrackTags(GeneratedPoseFavourTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); ShiftTrackTags(GeneratedWarpTrajLatTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); ShiftTrackTags(GeneratedWarpTrajLongTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift); cumTimeShift += localTimeShift; curStartTime = endWarpTime; } for (int i = 0; i < workingCurves.Count; ++i) { EditorUtility.DisplayProgressBar("Generate Modified Animation", "Generating Curves for clip: " + PrimaryClip.name, ((float)i) / ((float)workingCurves.Count)); AnimationUtility.SetEditorCurve(GeneratedClip, curveBindings[i], workingCurves[i]); } AnimationUtility.SetAnimationEvents(GeneratedClip, newEvents.ToArray()); EditorUtility.SetDirty(GeneratedClip); AssetDatabase.CreateAsset(GeneratedClip, a_directory + "/" + GeneratedClip.name + ".anim"); //AssetDatabase.AddObjectToAsset(GeneratedClip, m_targetPreProcessData); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(GeneratedClip)); EditorUtility.SetDirty(this); EditorUtility.ClearProgressBar(); } else { Debug.LogWarning("Warning: Cannot generate modified animation with no PrimaryClip in MxMAnimationClipComposite"); } } }
public void CopyData(MxMAnimationClipComposite a_copy) { PrimaryClip = a_copy.PrimaryClip; BeforeClips = new List<AnimationClip>(a_copy.BeforeClips); AfterClips = new List<AnimationClip>(a_copy.AfterClips); Looping= a_copy.Looping; IgnoreEdges = a_copy.IgnoreEdges; ExtrapolateTrajectory = a_copy.ExtrapolateTrajectory; FlattenTrajectory = a_copy.FlattenTrajectory; RuntimeSplicing = a_copy.RuntimeSplicing; UseSpeedMods = a_copy.UseSpeedMods; GlobalTags = a_copy.GlobalTags; GlobalFavourTags = a_copy.GlobalFavourTags; TagTracks = new List<TagTrack>(a_copy.TagTracks.Count + 1); foreach(TagTrack track in a_copy.TagTracks) { TagTracks.Add(new TagTrack(track)); } for (int i = 0; i < a_copy.TagTracks.Count; ++i) { TagTracks.Add(new TagTrack(a_copy.TagTracks[i])); } FavourTagTracks = new List<TagTrack>(a_copy.FavourTagTracks.Count + 1); foreach(TagTrack track in a_copy.FavourTagTracks) { FavourTagTracks.Add(new TagTrack(track)); } UserBoolTracks = new List<TagTrackBase>(a_copy.UserBoolTracks.Count + 1); foreach(TagTrackBase track in a_copy.UserBoolTracks) { UserBoolTracks.Add(new TagTrackBase(track)); } Events = new List<EventMarker>(a_copy.Events.Count + 1); foreach(EventMarker marker in a_copy.Events) { Events.Add(new EventMarker(marker)); } m_targetPreProcessData = a_copy.m_targetPreProcessData; m_targetAnimModule = a_copy.m_targetAnimModule; m_targetPrefab = a_copy.m_targetPrefab; PoseList = null; LeftFootStepTrack = new FootStepTagTrack(a_copy.LeftFootStepTrack); RightFootStepTrack = new FootStepTagTrack(a_copy.RightFootStepTrack); WarpPositionTrack = new TagTrackBase(a_copy.WarpPositionTrack); WarpRotationTrack = new TagTrackBase(a_copy.WarpRotationTrack); EnableRootMotionTrack = new TagTrackBase(a_copy.EnableRootMotionTrack); PoseFavourTrack = new FloatTagTrack(a_copy.PoseFavourTrack); WarpTrajLatTrack = new TagTrackBase(a_copy.WarpTrajLatTrack); WarpTrajLongTrack = new TagTrackBase(a_copy.WarpTrajLongTrack); MotionModifier = new MotionModifyData(a_copy.MotionModifier, this); }
public static void DetectFootsteps(IMxMAnim a_mxmAnim, GameObject a_targetModel, MxMPreProcessData a_preProcessData, AnimationModule a_animModule, float a_groundingThreshold, float a_minSpacing, float a_minDuration, float a_maxFootSpeed) { if ((a_preProcessData == null && a_animModule == null) || a_mxmAnim == null) { return; } AnimationClip targetClip = a_mxmAnim.TargetClip; if (targetClip == null) { return; } if (a_targetModel == null) { if (a_preProcessData == null) { a_targetModel = a_preProcessData.Prefab; } else if (a_animModule == null) { a_targetModel = a_animModule.Prefab; } if (a_targetModel == null) { Debug.LogError("MxM Footstep Detection - The MxMAnim you are trying to detect footsteps for has no target" + "model. This could occur if your target model is not set on the pre-processor, or your animation module" + "doesn't have a MotionMatch Config referenced."); return; } } List <FootStepData> leftFootStepData = new List <FootStepData>(); List <Vector2> leftFootStepPositions = new List <Vector2>(); List <FootStepData> rightFootStepData = new List <FootStepData>(); List <Vector2> rightFootStepPositions = new List <Vector2>(); GameObject model = GameObject.Instantiate(a_targetModel); model.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); Animator animator = model.GetComponent <Animator>(); if (animator == null) { animator = model.AddComponent <Animator>(); } animator.applyRootMotion = true; animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; Transform leftToeJoint = null; Transform rightToeJoint = null; bool getBonesByName = false; if (a_preProcessData != null) { getBonesByName = a_preProcessData.GetBonesByName; } else if (a_animModule != null) { getBonesByName = a_animModule.GetBonesByName; } if (!getBonesByName) { leftToeJoint = animator.GetBoneTransform(HumanBodyBones.LeftToes); rightToeJoint = animator.GetBoneTransform(HumanBodyBones.RightToes); } else { //Get generic joints? Debug.LogWarning("Automatic detection of footsteps is not currently supported for generic rigs"); return; } PlayableGraph playableGraph = PlayableGraph.Create(); playableGraph.SetTimeUpdateMode(DirectorUpdateMode.Manual); var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", animator); var animationMixer = AnimationMixerPlayable.Create(playableGraph, 1, true); playableOutput.SetSourcePlayable(animationMixer); var clipPlayable = AnimationClipPlayable.Create(playableGraph, targetClip); animationMixer.ConnectInput(0, clipPlayable, 0); animationMixer.SetInputWeight(0, 1f); clipPlayable.SetTime(0.0); clipPlayable.SetTime(0.0); playableGraph.Evaluate(0f); model.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); const float SixtyHz = 1f / 60f; float leftFootLowestY = leftToeJoint.position.y; float rightFootLowestY = rightToeJoint.position.y; for (float time = 0f; time <= targetClip.length; time += SixtyHz) { float leftFootY = leftToeJoint.position.y; float rightFootY = rightToeJoint.position.y; if (leftFootY < leftFootLowestY) { leftFootLowestY = leftFootY; } if (rightFootY < rightFootLowestY) { rightFootLowestY = rightFootY; } playableGraph.Evaluate(SixtyHz); } clipPlayable.SetTime(0.0); clipPlayable.SetTime(0.0); playableGraph.Evaluate(0f); bool leftFootGrounded = false; bool rightFootGrounded = false; float leftStepStartTime = 0f; float leftStepEndTime = 0f; float rightStepStartTime = 0f; float rightStepEndTime = 0f; model.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); float leftToeSpeed = 0f; float rightToeSpeed = 0f; Vector3 leftToeLastPos = leftToeJoint.position; Vector3 rightToeLastPos = rightToeJoint.position; for (float time = 0f; time <= targetClip.length; time += SixtyHz) { //Velocities leftToeSpeed = Vector3.Distance(leftToeLastPos, leftToeJoint.position) / SixtyHz; rightToeSpeed = Vector3.Distance(rightToeLastPos, rightToeJoint.position) / SixtyHz; leftToeLastPos = leftToeJoint.position; rightToeLastPos = rightToeJoint.position; //LEFT FOOT float leftFootDif = leftToeJoint.position.y - leftFootLowestY; if (leftFootDif < a_groundingThreshold && leftToeSpeed < a_maxFootSpeed) { if (leftFootGrounded == false) { leftStepStartTime = time; } leftFootGrounded = true; } else { if (leftFootGrounded == true) { leftStepEndTime = time; leftFootStepData.Add(new FootStepData()); leftFootStepPositions.Add(new Vector2(leftStepStartTime, leftStepEndTime)); } leftFootGrounded = false; } //RIGHT FOOT float rightFootDif = rightToeJoint.position.y - rightFootLowestY; if (rightFootDif < a_groundingThreshold && rightToeSpeed < a_maxFootSpeed) { if (rightFootGrounded == false) { rightStepStartTime = time; } rightFootGrounded = true; } else { if (rightFootGrounded == true) { rightStepEndTime = time; rightFootStepData.Add(new FootStepData()); rightFootStepPositions.Add(new Vector2(rightStepStartTime, rightStepEndTime)); } rightFootGrounded = false; } playableGraph.Evaluate(SixtyHz); } List <TagTrackBase> genericTagTracks = a_mxmAnim.GenericTagTracks; FootStepTagTrack leftFootTagTrack = genericTagTracks[0] as FootStepTagTrack; leftFootTagTrack.RemoveAllTags(); for (int i = 0; i < leftFootStepPositions.Count; ++i) { Vector2 footStepPosition = leftFootStepPositions[i]; //Combine footsteps that are too close to be real (This should be recursive) if (i + 1 < leftFootStepPositions.Count) { for (int k = i + 1; k < leftFootStepPositions.Count; ++k) { Vector2 nextFootStepPos = leftFootStepPositions[k]; if (nextFootStepPos.x - footStepPosition.y < a_minSpacing) { footStepPosition.y = nextFootStepPos.y; leftFootStepPositions.RemoveAt(k); --k; } else { break; } } } //Ignore footsteps that are too short to be real if (footStepPosition.y - footStepPosition.x < a_minDuration) { continue; } leftFootTagTrack.AddTag(footStepPosition.x, footStepPosition.y); } FootStepTagTrack rightFootTagTrack = genericTagTracks[1] as FootStepTagTrack; rightFootTagTrack.RemoveAllTags(); for (int i = 0; i < rightFootStepPositions.Count; ++i) { Vector3 footStepPosition = rightFootStepPositions[i]; //Combine footsteps that are too close to be real (This should be recursive) if (i + 1 < rightFootStepPositions.Count) { for (int k = i + 1; k < rightFootStepPositions.Count; ++k) { Vector2 nextFootStepPos = rightFootStepPositions[k]; if (nextFootStepPos.x - footStepPosition.y < a_minSpacing) { footStepPosition.y = nextFootStepPos.y; rightFootStepPositions.RemoveAt(k); --k; } else { break; } } } //Ignore footsteps that are too short to be real if (footStepPosition.y - footStepPosition.x < a_minDuration) { continue; } rightFootTagTrack.AddTag(footStepPosition.x, footStepPosition.y); } GameObject.DestroyImmediate(model); }