public void Evaluate() { if (m_Graph.IsValid()) { m_Graph.Evaluate(); } }
//... protected override void OnUpdate(float time, float previousTime) { if (isMasterTrack) { if (animator == null || !animator.gameObject.activeInHierarchy || !graph.IsValid()) { return; } var totalSiblingWeight = 0f; for (var i = 0; i < siblingTracks.Count; i++) { var siblingWeight = siblingTracks[i].compoundTrackWeight; masterMixer.SetInputWeight(i, siblingWeight); totalSiblingWeight += siblingWeight; } var animatorWeight = totalSiblingWeight < 1 ? 1 - totalSiblingWeight : 0; masterMixer.SetInputWeight(siblingTracks.Count + 1, animatorWeight); graph.Evaluate(time - previousTime); if (useRootMotion && useBakedRootMotion) { ApplyBakedRootMotion(time); } } }
protected override void OnUpdate(float time, float previousTime) { if (animator == null || !animator.gameObject.activeInHierarchy) { return; } #if UNITY_2017_1_OR_NEWER if (!graph.IsValid()) { return; } baseClipPlayable.SetTime(time * basePlaybackSpeed); graph.Evaluate(0); #elif UNITY_5_6_OR_NEWER if (!graph.IsValid()) { return; } baseClipPlayableHandle.time = time * basePlaybackSpeed; graph.Evaluate(0); #else if (!mixerPlayable.IsValid()) { return; } if (!animator.isInitialized) { animator.Play(mixerPlayable); } if (baseAnimationClip != null) { var basePlayable = mixerPlayable.GetInput(0); basePlayable.time = time * basePlaybackSpeed; mixerPlayable.SetInput(basePlayable, 0); } animator.Update(0); #endif if (useRootMotion && useBakedRootMotion) { ApplyBakedRootMotion(time); } }
/// <summary> /// Use animation Playables API to control keyed values, blended between the first frame of 2 animation clips. /// </summary> /// <param name="valueForAdaptationCurve">A value to evaluate into adaptation curve producing a real blend value for 2 clips.</param> /// <param name="animator">The control target for animation playables. The clips used must be able to control the keyed fields traveling down from this animator component.</param> public void Adapt(float valueForAdaptationCurve, Animator animator) { if (!Adaptable) { return; } float blend = adaptationCurve.Evaluate(valueForAdaptationCurve); //Connect up a playable graph, evaluate once, then we're done with them. PlayableGraph pg = PlayableGraph.Create("AdaptationGraph"); pg.SetTimeUpdateMode(DirectorUpdateMode.Manual); var mixer = AnimationMixerPlayable.Create(pg, 2, normalizeWeights: true); //Not sure if the mixer should be "cross fade" like this, or should we do 0~1 weight over 1 weight? //But I think that's for AnimationLayerMixerPlayable ? mixer.SetInputWeight(inputIndex: 0, weight: 1 - blend); mixer.SetInputWeight(inputIndex: 1, weight: blend); var normalStateAcp = AnimationClipPlayable.Create(pg, normalState); var fullyAdaptedStateAcp = AnimationClipPlayable.Create(pg, fullyAdaptedState); pg.Connect(normalStateAcp, sourceOutputPort: 0, mixer, destinationInputPort: 0); pg.Connect(fullyAdaptedStateAcp, sourceOutputPort: 0, mixer, destinationInputPort: 1); var output = AnimationPlayableOutput.Create(pg, "AdaptationGraphOutput", animator); output.SetSourcePlayable(mixer); pg.Evaluate(); pg.Destroy(); }
private void FixedUpdate() { if (mode == DirectorUpdateMode.Manual) { graph.Evaluate(Time.fixedDeltaTime); } }
public void SampleAnimation(AnimationClip clip, float time) { #if UNITY_2018_3_OR_NEWER ResetTranformRoot(); va.UpdateSyncEditorCurveClip(); if (animator != null) { PlayableGraphReady(clip); #if UNITY_2019_1_OR_NEWER m_AnimationClipPlayable.SetTime(time); #else //Loop cannot be disabled because there is no SetOverrideLoopTime var subTime = time; if (subTime > clip.length) { subTime = clip.length - 0.0000001f; } m_AnimationClipPlayable.SetTime(subTime); #endif m_PlayableGraph.Evaluate(); } else if (animation != null) { SampleAnimationLegacy(clip, time); } #else SampleAnimationLegacy(clip, time); #endif }
void OnEnable() { m_Animator = GetComponent <Animator>(); // Setting to Always animate because on the first frame the renderer can be not visible which break syncGoal on start up m_Animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; if (!m_Animator.avatar.isHuman) { throw new InvalidOperationException("Avatar must be a humanoid."); } m_Graph = PlayableGraph.Create(); m_Graph.SetTimeUpdateMode(DirectorUpdateMode.GameTime); var output = AnimationPlayableOutput.Create(m_Graph, "output", m_Animator); var clip = SampleUtility.LoadAnimationClipFromFbx("DefaultMale/Models/DefaultMale_Humanoid", "Idle"); var clipPlayable = AnimationClipPlayable.Create(m_Graph, clip); clipPlayable.SetApplyFootIK(false); clipPlayable.SetApplyPlayableIK(false); var job = new FullBodyIKJob(); job.stiffness = stiffness; job.maxPullIteration = maxPullIteration; SetupIKLimbHandle(ref job.leftArm, HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand); SetupIKLimbHandle(ref job.rightArm, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand); SetupIKLimbHandle(ref job.leftLeg, HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot); SetupIKLimbHandle(ref job.rightLeg, HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot); m_LeftFootEffector = SetupEffector(ref job.leftFootEffector, "LeftFootEffector"); m_RightFootEffector = SetupEffector(ref job.rightFootEffector, "RightFootEffector"); m_LeftHandEffector = SetupEffector(ref job.leftHandEffector, "LeftHandEffector"); m_RightHandEffector = SetupEffector(ref job.rightHandEffector, "RightHandEffector"); m_LeftKneeHintEffector = SetupHintEffector(ref job.leftKneeHintEffector, "LeftKneeHintEffector"); m_RightKneeHintEffector = SetupHintEffector(ref job.rightKneeHintEffector, "RightKneeHintEffector"); m_LeftElbowHintEffector = SetupHintEffector(ref job.leftElbowHintEffector, "LeftElbowHintEffector"); m_RightElbowHintEffector = SetupHintEffector(ref job.rightElbowHintEffector, "RightElbowHintEffector"); m_LookAtEffector = SetupLookAtEffector(ref job.lookAtEffector, "LookAtEffector"); m_BodyRotationEffector = SetupBodyEffector(ref job.bodyEffector, "BodyEffector"); m_IKPlayable = AnimationScriptPlayable.Create <FullBodyIKJob>(m_Graph, job, 1); m_IKPlayable.ConnectInput(0, clipPlayable, 0, 1.0f); output.SetSourcePlayable(m_IKPlayable); m_Graph.Play(); m_Graph.Evaluate(0); SyncIKFromPose(); ResetIKWeight(); }
private void AnimationFrameUpdate() { //mixerがない、アニメーション速度が0以下 if ((!(mixer.IsValid())) || (animationSpeed <= 0)) { return; } mixer.SetTime(0); //ブレンドフレームが設定されていれば if (changeWeightFrame > 0) { float changeMinus = (1.0f - ((float)frameCount / (float)changeWeightFrame)); //フレームごとにブレンド mixer.SetInputWeight(0, 1.0f - changeMinus); mixer.SetInputWeight(1, changeMinus); //完全にブレンドしたら数字を0に if (frameCount >= changeWeightFrame) { changeWeightFrame = 0; } } //なければ普通に再生 else { mixer.SetInputWeight(0, 1.0f); mixer.SetInputWeight(1, 0); } //更新 if (beforeClipPlayable.IsValid()) { beforeClipPlayable.SetTime(beforeClipTime); } playableGraph.Evaluate((1.0f / nowClip.frameRate) * animationSpeed); //フレーム取得 nowFrame = (int)(((float)nowClipPlayable.GetTime() * nowClip.frameRate) * (1 / animationSpeed)); bool endAnimation = (nowFrame >= (int)((nowClip.length * nowClip.frameRate * (1.0f / animationSpeed)))); //現在のフレーム数が最大であれば if (endAnimation) { if (nowClip.isLooping) { mixer.SetTime(0); nowClipPlayable.SetTime(0); if (beforeClipPlayable.IsValid()) { beforeClipPlayable.SetTime(0); } } } //アニメーションが終わっているかどうかの判定 endAnimFrag = endAnimation; frameCount++; if (frameCount >= int.MaxValue - 1) { frameCount = 0; } }
protected override void OnSetValue(float t) { if (this.enabled) { if (animator != null && playableGraph.IsValid()) { clipPlayable.SetTime(t * clip.length); playableGraph.Evaluate(); } } }
protected override void OnUpdate(float time, float previousTime) { if (animator == null || !animator.gameObject.activeInHierarchy) { return; } if (!graph.IsValid()) { return; } baseClipPlayableHandle.time = time * basePlaybackSpeed; graph.Evaluate(0); if (useRootMotion && useBakedRootMotion) { ApplyBakedRootMotion(time); } }
public void Update() { if (!EditorApplication.isPlaying) { //graph.SetTimeUpdateMode(UnityEngine.Playables.DirectorUpdateMode.Manual); graph.Evaluate(); } graph.Evaluate(); for (int i = 0; i < poses.Count; i++) { try { poseMixer.SetInputWeight(i, poses[i].Weight); } catch { poses.RemoveAt(i); } } }
//... protected override void OnUpdate(float time, float previousTime) { if (isMasterTrack) { if (animator == null || !animator.gameObject.activeInHierarchy || !graph.IsValid()) { return; } for (var i = 0; i < siblingTracks.Count; i++) { masterMixer.SetInputWeight(i, siblingTracks[i].compoundTrackWeight); } graph.Evaluate(0); if (useRootMotion && useBakedRootMotion) { ApplyBakedRootMotion(time); } } }
public void UpdateGraph(float dt) { if (!isPlaying || isPause) { return; } sampleTimer += dt; if (sampleTimer > sampleIntervalp) { m_Graph.Evaluate(sampleTimer); sampleTimer = 0; } }
private void Update() { if (nowPlayAnimation == null) { if (mixer.IsValid()) { mixer.Destroy(); } _beforeNowPlayClip = null; } else if (_beforeNowPlayClip != nowPlayAnimation) { SetPlayAnimation(nowPlayAnimation, frameSpeed, changeFrameNow); } SetNextAnimationPlayable(); if (playableGraph.IsValid() && mixer.IsValid()) { if (frameSpeed <= 0) { return; } if (changeWeightFrame > 0) { mixer.SetInputWeight(0, (1.0f - num) - ((1.0f) - (((float)_nowChangeFrame) / ((float)changeWeightFrame)))); mixer.SetInputWeight(1, num + ((1.0f) - (((float)_nowChangeFrame) / ((float)changeWeightFrame)))); if (_nowChangeFrame >= changeWeightFrame) { changeWeightFrame = 0; _nowChangeFrame = 0; } _nowChangeFrame++; } else { mixer.SetInputWeight(0, (1.0f - num)); mixer.SetInputWeight(1, num); } playableGraph.Evaluate((1.0f / nowPlayAnimation.frameRate) * frameSpeed); nowFrame = (int)(((float)mixer.GetTime() * nowPlayAnimation.frameRate) * frameSpeed); //ループ if (nowFrame >= (nowPlayAnimation.length * nowPlayAnimation.frameRate * frameSpeed) && nowPlayAnimation.isLooping) { mixer.SetTime(0); _nowPlayAnimation.SetTime(0); if (_beforePlayAnimation.IsValid()) { _beforePlayAnimation.SetTime(0); } } } }
public void AnimationManualUpdate() { if (!_isInitialized) { return; } if (_updateMode != DirectorUpdateMode.Manual) { return; } _playableGraph.Evaluate(Time.deltaTime); }
public void Update(float deltaTime) { _graph.Evaluate(deltaTime); // 更新所有层级 for (int i = 0; i < _mixers.Count; i++) { var mixer = _mixers[i]; if (mixer.IsConnect) { mixer.Update(deltaTime); } } }
public void Update() { graph.Evaluate(); for (int i = 0; i < poses.Count; i++) { try { poseMixer.SetInputWeight(i, poses[i].Weight); } catch { poses.RemoveAt(i); } } }
void Update() { if (!mixer.IsValid() || Speed == 0) { return; } var cWeight = mixer.GetInputWeight(0); if (cWeight < 1) { cWeight = Mathf.Lerp(0, 1, (Time.time - changeTime) / blendTime); mixer.SetInputWeight(0, cWeight); mixer.SetInputWeight(1, 1 - cWeight); } graph.Evaluate(Time.deltaTime * Speed); }
public void Evaluate(float dt) { m_SyncSceneToStreamLayer?.Update(m_RigLayers); if (m_RigLayers != null) { foreach (var layer in m_RigLayers) { if (layer.IsValid() && layer.active) { layer.Update(); } } } m_Graph.Evaluate(dt); }
public override void UpdateMovement(out Vector3 goalPosition, out Quaternion goalRotation, float deltaTime) { // Remember pose before animation Vector3 _positionBeforeAnim = _transform.position; Quaternion _rotationBeforeAnim = _transform.rotation; // Update animation _playableGraph.Evaluate(deltaTime); // Set our platform's goal pose to the animation's goalPosition = _transform.position; goalRotation = _transform.rotation; // Reset the actual transform pose to where it was before evaluating. // This is so that the real movement can be handled by the physics mover; not the animation _transform.position = _positionBeforeAnim; _transform.rotation = _rotationBeforeAnim; }
public void ApplyState(ref PlayerState state) { StateMachine.Presimulate(ref state); var stateInfo = GetControllerState(ref state); if (stateInfo == null) { return; } foreach (var controllerState in _states) { controllerState.Disconnect(); controllerState.SetWeight(0f); } stateInfo.Connect(); stateInfo.SetWeight(1f); stateInfo.SetTime(ref state); _playableGraph.Evaluate(); }
public void Tick(float deltaTime) { _playableGraph.Evaluate(deltaTime); for (int i = 0; i < AnimationPlayLayers.Length; i++) { var currLayer = AnimationPlayLayers[i]; if (currLayer.GetWeight(out var aW, out var bW)) { mixerPlayable.SetInputWeight(currLayer.aInputIndex, aW); mixerPlayable.SetInputWeight(currLayer.bInputIndex, bW); if (aW <= 0) { mixerPlayable.DisconnectInput(currLayer.aInputIndex); currLayer.EndBInput(); } } currLayer.Time += deltaTime; } }
public void GenerateRootLookupTable() { AnimationClip primaryClip = this.TargetClip; if (primaryClip != null) { if (m_targetPrefab == null) { if (m_targetPreProcessData != null) { m_targetPrefab = m_targetPreProcessData.Prefab; } else if(m_targetAnimModule != null) { m_targetPrefab = m_targetPreProcessData.Prefab; } } if (m_targetPrefab != null) { if (m_rootPosLookupTable == null) m_rootPosLookupTable = new List<Vector3>(); if (m_rootRotLookupTable == null) m_rootRotLookupTable = new List<Quaternion>(); if (m_rootSpeedLookupTable == null) m_rootSpeedLookupTable = new List<float>(); m_rootPosLookupTable.Clear(); m_rootRotLookupTable.Clear(); m_rootSpeedLookupTable.Clear(); //Instantiate prefab and setup playable graph GameObject previewPrefab = Instantiate(m_targetPrefab); Animator previewAnimator = previewPrefab.GetComponent<Animator>(); if (previewAnimator == null) { previewAnimator = previewPrefab.AddComponent<Animator>(); previewAnimator.applyRootMotion = true; } PlayableGraph playableGraph = PlayableGraph.Create(); playableGraph.SetTimeUpdateMode(DirectorUpdateMode.Manual); var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", previewAnimator); AnimationMixerPlayable animationMixer = AnimationMixerPlayable.Create(playableGraph, 1, true); playableOutput.SetSourcePlayable(animationMixer); var playableClip = AnimationClipPlayable.Create(playableGraph, primaryClip); animationMixer.ConnectInput(0, playableClip, 0); animationMixer.SetInputWeight(0, 1f); playableClip.SetTime(0.0); playableClip.SetTime(0.0); previewPrefab.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); playableGraph.Evaluate(0f); double sampleRate = 1.0 / primaryClip.frameRate; //Fill the lookup table with root positions for (double animTime = 0.0; animTime <= primaryClip.length; animTime += sampleRate) { m_rootPosLookupTable.Add(previewPrefab.transform.position); m_rootRotLookupTable.Add(previewPrefab.transform.rotation); playableGraph.Evaluate((float)sampleRate); } playableGraph.Destroy(); GameObject.DestroyImmediate(previewPrefab); if (m_rootPosLookupTable.Count > 1) { //Generate the linear speed lookup table for (int i = 1; i < m_rootPosLookupTable.Count; ++i) { Vector3 startPos = m_rootPosLookupTable[i - 1]; Vector3 endPos = m_rootPosLookupTable[i]; m_rootSpeedLookupTable.Add(Vector3.Distance(endPos, startPos) / (float)sampleRate); } } else { m_rootSpeedLookupTable.Add(0f); } m_rootSpeedLookupTable.Insert(0, m_rootSpeedLookupTable[0]); } } }
private void DrawAnimationStatePreview() { EditorUtilities.Splitter(); var oldPreviewMode = previewMode; EditorUtilities.DrawHorizontal(() => { EditorGUILayout.LabelField("Preview mode"); EditorGUI.BeginDisabledGroup(previewMode == PreviewMode.Automatic); if (GUILayout.Button("Automatic")) { previewMode = PreviewMode.Automatic; } EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(previewMode == PreviewMode.Manual); if (GUILayout.Button("Manual")) { previewMode = PreviewMode.Manual; } EditorGUI.EndDisabledGroup(); }); if (oldPreviewMode == PreviewMode.Manual && previewMode == PreviewMode.Automatic) { automaticPreviewLastTime = Time.realtimeSinceStartup; } if (previewMode == PreviewMode.Manual) { var oldPreviewTime = previewTime; previewTime = EditorGUILayout.Slider(previewTime, 0f, currentPreviewedState.Duration); previewGraph.Evaluate(previewTime - oldPreviewTime); } else { var currentTime = Time.realtimeSinceStartup; var deltaTime = currentTime - automaticPreviewLastTime; automaticPreviewLastTime = currentTime; previewTime = (previewTime + deltaTime) % currentPreviewedState.Duration; previewGraph.Evaluate(deltaTime); var oldVal = previewTime; previewTime = EditorGUILayout.Slider(previewTime, 0f, currentPreviewedState.Duration); if (oldVal != previewTime) { previewMode = PreviewMode.Manual; } } SceneView.RepaintAll(); if (GUILayout.Button("Stop preview")) { StopPreviewing(); } }
public override void InitForAvatar() { StartVrcHooks(); AvatarAnimator.applyRootMotion = false; AvatarAnimator.runtimeAnimatorController = null; AvatarAnimator.updateMode = AnimatorUpdateMode.Normal; AvatarAnimator.cullingMode = AnimatorCullingMode.CullCompletely; DestroyGraphs(); var layerList = _avatarDescriptor.baseAnimationLayers.ToList(); layerList.AddRange(_avatarDescriptor.specialAnimationLayers); layerList.Sort(ModuleVrc3Styles.Data.LayerSort); _playableGraph = PlayableGraph.Create("Gesture Manager 3.1"); var externalOutput = AnimationPlayableOutput.Create(_playableGraph, "Gesture Manager", AvatarAnimator); var playableMixer = AnimationLayerMixerPlayable.Create(_playableGraph, layerList.Count + 1); externalOutput.SetSourcePlayable(playableMixer); _fromBlend.Clear(); _avatarClips.Clear(); _weightControllers = new RadialWeightController[layerList.Count]; _humanAnimatorPlayables = new AnimatorControllerPlayable[layerList.Count]; for (var i = 0; i < layerList.Count; i++) { var vrcAnimLayer = layerList[i]; var iGraph = i + 1; if (vrcAnimLayer.animatorController) { foreach (var clip in vrcAnimLayer.animatorController.animationClips) { _avatarClips.Add(clip); } } var isFx = vrcAnimLayer.type == VRCAvatarDescriptor.AnimLayerType.FX; var isAdd = vrcAnimLayer.type == VRCAvatarDescriptor.AnimLayerType.Additive; var isPose = vrcAnimLayer.type == VRCAvatarDescriptor.AnimLayerType.IKPose || vrcAnimLayer.type == VRCAvatarDescriptor.AnimLayerType.TPose; var isAction = vrcAnimLayer.type == VRCAvatarDescriptor.AnimLayerType.Sitting || vrcAnimLayer.type == VRCAvatarDescriptor.AnimLayerType.Action; var limit = isPose || isAction; var controller = vrcAnimLayer.animatorController ? vrcAnimLayer.animatorController : ModuleVrc3Styles.Data.ControllerOf[vrcAnimLayer.type]; var mask = vrcAnimLayer.isDefault || isFx ? ModuleVrc3Styles.Data.MaskOf[vrcAnimLayer.type] : vrcAnimLayer.mask; if (!controller) { continue; } _humanAnimatorPlayables[i] = AnimatorControllerPlayable.Create(_playableGraph, Vrc3ProxyOverride.OverrideController(controller)); _weightControllers[i] = new RadialWeightController(playableMixer, iGraph); for (var j = 0; j < _humanAnimatorPlayables[i].GetLayerCount(); j++) { _humanAnimatorPlayables[i].SetLayerWeight(j, 1f); } playableMixer.ConnectInput(iGraph, _humanAnimatorPlayables[i], 0, 1); _fromBlend[vrcAnimLayer.type] = _weightControllers[i]; if (limit) { playableMixer.SetInputWeight(iGraph, 0f); } if (isAdd) { playableMixer.SetLayerAdditive((uint)iGraph, true); } if (mask) { playableMixer.SetLayerMaskFromAvatarMask((uint)iGraph, mask); } } _playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime); _playableGraph.Play(); _playableGraph.Evaluate(0f); RadialMenu.Set(AvatarAnimator, Menu, Parameters, _humanAnimatorPlayables); RadialMenu.GetParam("TrackingType")?.InternalSet(1f); RadialMenu.GetParam("Upright")?.InternalSet(1f); RadialMenu.GetParam("Grounded")?.InternalSet(1f); RadialMenu.GetParam("VelocityX")?.Amplify(-7f); RadialMenu.GetParam("VelocityZ")?.Amplify(7f); RadialMenu.GetParam("AvatarVersion")?.InternalSet(3f); RadialMenu.GetParam("Seated")?.OnChange(OnSeatedModeChange); }
public void Evaluate(float deltaTime) { graph.Evaluate(deltaTime); }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { if (animator == null) { if (playerData is GameObject) { animator = ((GameObject)playerData).GetComponent <Animator>(); } else if (playerData is Animator) { animator = playerData as Animator; } } if (animator == null) { return; } Vector3 defaultPosition = animator.gameObject.transform.position; Quaternion defaultRotation = animator.gameObject.transform.rotation; int inputCount = playable.GetInputCount(); if (clips.Count <= 0) { mixer = AnimationPlayableUtilities.PlayMixer(animator, inputCount, out playableGraph); } Vector3 blendedPosition = Vector3.zero; Quaternion blendedRotation = new Quaternion(0f, 0f, 0f, 0f); RuntimeAnimatorController controller = animator ? animator.runtimeAnimatorController as RuntimeAnimatorController : null; for (int i = 0; i < inputCount; i++) { ScriptPlayable <AnimatorControlBehavior> playableInput = (ScriptPlayable <AnimatorControlBehavior>)playable.GetInput(i); AnimatorControlBehavior input = playableInput.GetBehaviour(); float inputWeight = playable.GetInputWeight(i); float normalisedTime = (float)(playableInput.GetTime() * input.inverseDuration); if (input.Clip == null || input.Clip.name != input.ClipName) { for (int j = 0; j < controller.animationClips.Length; j++) { AnimationClip clip = controller.animationClips[j]; if (clip.name == input.ClipName) { input.Clip = clip; } } } if (input.Clip) { if (clips.Count <= i) { AnimationClipPlayable clipplay = AnimationClipPlayable.Create(playableGraph, input.Clip); playableGraph.Connect(clipplay, 0, mixer, i); clips.Add(clipplay); } mixer.SetInputWeight(i, inputWeight); clips[i].SetTime((double)normalisedTime * input.Clip.length); clips[i].SetSpeed(0); } } if (!Application.isPlaying) { playableGraph.Evaluate(); } }
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); }
public void OnGUI(Rect r, GUIStyle background) { if (Event.current.type == EventType.Repaint) { #region TimeControl { var beforePlaying = uTimeControl.playing; #if UNITY_2019_1_OR_NEWER var beforeCurrentTime = uTimeControl.currentTime; uTimeControl.Update(); if (uTimeControl.playing && uTimeControl.currentTime < beforeCurrentTime) { loopCount++; } #else uTimeControl.Update(); #endif if (beforePlaying != uTimeControl.playing) { uTimeControl.playing = beforePlaying; } } #endregion { var clip = dg_get_m_SourcePreviewMotion(instance); uTimeControl.loop = true; uTimeControl.startTime = 0f; uTimeControl.stopTime = clip.length; dg_set_fps(instance, (int)clip.frameRate); if (!clip.legacy && animator != null) { dg_set_ShowIKOnFeetButton(animator.isHuman && clip.isHumanMotion); #if UNITY_2019_1_OR_NEWER if (m_PlayableGraph.IsValid()) { if (m_AnimationOffsetPlayable.IsValid()) { m_UAnimationOffsetPlayable.SetPosition(m_AnimationOffsetPlayable, transformPoseSave.startPosition); m_UAnimationOffsetPlayable.SetRotation(m_AnimationOffsetPlayable, transformPoseSave.startRotation); } m_AnimationClipPlayable.SetApplyFootIK(isIKOnFeet); m_AnimationClipPlayable.SetTime(loopCount * clip.length + uTimeControl.currentTime); #if VERYANIMATION_ANIMATIONRIGGING if (m_RigBuilder != null && m_RigBuilder.enabled && m_RigBuilder.layers.Count > 0) { m_RigBuilder.UpdatePreviewGraph(m_PlayableGraph); } #endif m_PlayableGraph.Evaluate(); } #else if (animator.runtimeAnimatorController != null) { AnimationClipSettings animationClipSettings = AnimationUtility.GetAnimationClipSettings(clip); if (m_State != null) { m_State.iKOnFeet = isIKOnFeet; } var normalizedTime = animationClipSettings.stopTime - animationClipSettings.startTime == 0.0 ? 0.0f : (float)((uTimeControl.currentTime - animationClipSettings.startTime) / (animationClipSettings.stopTime - animationClipSettings.startTime)); animator.Play(0, 0, normalizedTime); animator.Update(uTimeControl.deltaTime); } #endif } else if (animation != null) { dg_set_ShowIKOnFeetButton(false); clip.SampleAnimation(gameObject, uTimeControl.currentTime); } } } dg_DoAvatarPreview(r, background); if (animator.applyRootMotion && transformPoseSave != null) { var rect = r; rect.yMin = rect.yMax - 40f; rect.yMax -= 15f; var invRot = Quaternion.Inverse(transformPoseSave.originalRotation); var pos = invRot * (gameObject.transform.position - transformPoseSave.originalPosition); var rot = (invRot * gameObject.transform.rotation).eulerAngles; EditorGUI.DropShadowLabel(rect, string.Format("Root Motion Position {0}\nRoot Motion Rotation {1}", pos, rot)); } }