Hi there! Hopefully it's an easy one and I'm just missing something very obvious. π
TL;DR I want my Unity project to use 3 animation tracks (0,1, 2) but I run into stutter/glitch issues when tracks 1 and 2 use the same bones (here - eye bones) even if they don't use them at the same time. (more explained below).
I assigned the blink animation on track 2, track 1 is for intermittent idle animations (like look around and such). Track 0 is for breathing, causes no issues. Now, for the first few seconds in game, all works fine - the blink runs its course every few seconds, the intermittent idle works alright too, but as soon as an idle animation that uses eye bones runs at least once (and it runs fine the first time) it... Locks the eye bones? and causes different issues like:
- Blink not playing at all, or
-Blink ending abruptly (so closing half way and not completely), and/or
-Idle animations not moving eyes at all (not looking around, not changing the eyelid positions to e.g. look down)
At first I thought maybe if these run together on accident they somehow cause issues? So I created a bool isPlayingAnimation on my idle animation coroutine, with blink not allowed to set its animation if the bool is true, but it still persisted... Okay. Then I changed Mix Duration to 0, maybe the animations are getting lost in transition time (somehow?) but no luck there either. Maybe clearing the track before the animation to have a blank slate? Nope. And now I'm out of ideas. Any help appreciated!!
(code below if needed)
MainSpriteIdle
`
[SpineAnimation] public string[] neutralIdle = { "ear-twitch", "head-side", "head-side-look-away", "look-around", "tail-swish" };
[SpineAnimation] public string[] happyIdle = { "ear-twitch", "head-side","shrug", "head-side-look-away", "look-around", "tail-swish" };
public int activeAnimationIndex = 0;
public string[] idleList;
private GameSession gameSession;
[SerializeField]private int moodIndex;
public bool isPlayingAnimation = false;
SkeletonAnimation skeletonAnimation;
private void Awake()
{
skeletonAnimation = this.GetComponent<SkeletonAnimation>();
}
private void Start()
{
gameSession = FindObjectOfType<GameSession>().GetComponent<GameSession>();
StartCoroutine(PlayRandomAnimation());
}
// Update is called once per frame
void Update()
{
//listen for mood changes
if (gameSession.isInitialised && moodIndex != gameSession.mood)
AssignListBasedOnMood();
}
private IEnumerator PlayRandomAnimation()
{
AssignListBasedOnMood();
while (true)
{
float randomInterval = UnityEngine.Random.Range(10f, 12f);
yield return new WaitForSeconds(randomInterval);
//yield return new WaitForSeconds(2f);
if (idleList != null)
{
// Generate a random index for the animation array
activeAnimationIndex = UnityEngine.Random.Range(0, idleList.Length);
skeletonAnimation.AnimationState.ClearTrack(1);
// Play the selected animation
//skeletonAnimation.AnimationState.SetAnimation(1, idleList[activeAnimationIndex], false); //(will uncomment after testing)
skeletonAnimation.AnimationState.SetAnimation(1, happyIdle[2], false); //happyIdle[2] is an animation that uses eye bones
isPlayingAnimation = true;
yield return new WaitForSeconds(skeletonAnimation.AnimationState.GetCurrent(1)?.Animation?.Duration ?? 0f);
isPlayingAnimation = false;
}
else continue;
}
}
private void AssignListBasedOnMood()
{
if (gameSession == null)
gameSession = FindObjectOfType<GameSession>().GetComponent<GameSession>();
moodIndex = gameSession.mood;
if (moodIndex >= 60)
idleList = happyIdle;
if(moodIndex >= 30 && moodIndex < 60)
{
idleList = neutralIdle;
}
if(moodIndex < 30)
{
idleList = null;
}
}
`
Blinking
`
private float minimumDelay = 4f;
private float maximumDelay = 7f;
private MainSpriteIdle spriteIdleScript;
void Start()
{
spriteIdleScript = FindObjectOfType<MainSpriteIdle>().GetComponent<MainSpriteIdle>();
StartCoroutine(Blink());
}
void Update()
{
}
private IEnumerator Blink()
{
SkeletonAnimation skeletonAnimation = this.GetComponent<SkeletonAnimation>();
while (true)
{
yield return new WaitForSeconds(Random.Range(minimumDelay, maximumDelay));
if (spriteIdleScript.isPlayingAnimation)
continue;
skeletonAnimation.AnimationState.ClearTrack(2);
skeletonAnimation.AnimationState.SetAnimation(2, "blink-neutral" , false);
Debug.Log("Blinked");
}
}`