主要目标是逐一播放列表中的所有动画,以播放第一个动画,等待其完成播放,然后开始下一个动画。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayAnimations : MonoBehaviour
{
public Animator animator;
private List<AnimationClip> clips = new List<AnimationClip>();
// Start is called before the first frame update
void Start()
{
foreach (AnimationClip ac in animator.runtimeAnimatorController.animationClips)
{
StartCoroutine(PlayAll(ac.name, ac.length));
}
}
public IEnumerator PlayAll(string stateName, float length)
{
animator.Play(stateName);
yield return new WaitForSeconds(length);
}
// Update is called once per frame
void Update()
{
}
}
但是它只播放一个动画剪辑,而动画控制器中有两个。为什么呢
它只播放第二个,而第一个不播放StateMachine默认状态的播放。
答案 0 :(得分:1)
您要在“相同”时间(至少在同一帧中)针对不同状态/动画启动所有协程,因此它们都“同时”运行animator.Play
。
因此在第一帧中,两个协程都设置了相应的状态,首先是第一个动画,然后是第二个动画,等等。
=>您只有列表中的最后一个实际运行,因为它是唯一不会因随后的animator.Play
调用而被“推翻”的计算机。
相反,请将您的for循环移至协同程序:
void Start()
{
StartCoroutine(PlayAll());
}
public IEnumerator PlayAll()
{
foreach (AnimationClip ac in animator.runtimeAnimatorController.animationClips)
{
animator.Play(ac.name);
yield return new WaitForSeconds(ac.length);
}
}
但是实际上StateMachine的整个想法都在进行过渡..因此,您可以将两个状态/动画与具有过渡的过渡简单地联系起来
UseExitTime
已启用ExitTime = 1
Duration
(如果需要,可以过渡或淡入)0
然后它会自动转到第一个动画后的下一个动画。 (您现在甚至可以通过简单地过渡到第一个状态来循环播放它们。)
因此,您实际上根本不需要任何脚本。
否则,您也可以使用Animation组件,而不使用状态,过渡,层和控制器。
代码只会稍有不同:
// Assuming here this script is attached to the same object as the Animation component
// Ofcourse you can also keep it public and reference the component yourself
private Animation animation;
public List<AnimationClip> clips = new List<AnimationClip>();
private void Awake()
{
animation = GetComponent<Animation>();
}
private void Start()
{
StartCoroutine(PlayAll());
}
private IEnumerator PlayAll()
{
foreach(var clip in clips)
{
animation.Play(clip.name);
yield return new WaitForSeconds(clip.length);
}
}
Animation
组件被标记为旧版,但是由于其简单易用,例如您的用例。