How to force an animation state in an animator controller to go to the exact play percentage of an animation state of equal length in a different animator controller
So i've been struggling all day trying to get an animation i made in blender to work in unity. The hoe is constrained to an armature (call it hoe_to_hands_armature), and the hands are also constrained to this very same armature. The character has his own armature (call it player_armature), which totals two armatures for the animation. Note that the armatures contain the animations. That is, the hoe_to_hands_armature "contains" the animation that move this hoe and hands about, creating the hoe movements in the animation. With the player_armature "containing" the animation that move the player about. I imported the player model and player_armature into unity, then did the same for the hoe model and hoe_to_hands armature. I then made an empty game object in the unity scene, and made the player_armature and hoe_to_hands_armature children of said empty. I also added separate animation controllers and avatars to both the player_armature, and the hoe_to_hands_armature. The animation clip of both armatures are the exact same length. The first loop of the animation works perfectly, successive loops see the player_armature progressively "falling behind" the hoe_to_hands_armature. So my question is, how do i force either animation state in the two separate anim controllers to "go" to the playtime/progression of the the other? Demo
Answer by Arthur_Gentz · Oct 09, 2021 at 11:37 AM
Found a solution, by just comparing the 'percent completion' of one animation state with that of the other. If the difference between 'percent completions' is large enough, i simply play one of the two while using the normalized time of the other.
using System;
using UnityEngine;
public class SyncPlaybackTimes : MonoBehaviour
{
public string playerAnimStateName;
public string propAnimStateName;
[SerializeField] private Animator _playerAnimator;
[SerializeField] private Animator _propAnimator;
private AnimatorStateInfo _playerAnimStateInfo;
private AnimatorStateInfo _propAnimStateInfo;
private void LateUpdate()
{
SyncPropWithCharAnim();
}
private void SyncPropWithCharAnim()
{
_propAnimStateInfo = _playerAnimator.GetCurrentAnimatorStateInfo(0);
float charAnimCompletion = PlaybackPercent(_propAnimStateInfo);
_playerAnimStateInfo = _propAnimator.GetCurrentAnimatorStateInfo(0);
float propAnimCompletion = PlaybackPercent(_playerAnimStateInfo);
float syncDiff = propAnimCompletion - charAnimCompletion;
bool synced = Math.Abs(syncDiff) < 0.01f;
if ( synced ) return;
//Both the character and prop animations are the same length and ought to have started at the exact moment. So if the prop animation goes out of sync, simply re-sync by (re)playing the prop animation but started at the normalized time (progress) of the character animation
_propAnimator.Play(propAnimStateName, 0, _playerAnimStateInfo.normalizedTime);
}
public float PlaybackPercent(AnimatorStateInfo animationStateInfo)
{
float normTime = animationStateInfo.normalizedTime;
float percentComplete = normTime - Mathf.Floor(normTime);
return percentComplete;
}
}
If anyone knows of a simpler less hacky solution, please share.
Your answer
Follow this Question
Related Questions
I cannot switch the current animation state to another state immediately. 0 Answers
Mecanim, get state percent complete when a transition occurs? 0 Answers
Animation State of Controller not showing in Inspector when clicked 10 Answers
Animator Override controller SubstateMachine issue 0 Answers
Animation play not working C# 0 Answers