【发布时间】:2019-01-01 23:44:58
【问题描述】:
我有 12 个状态,它们都通过循环中的转换连接。 所以演奏的流程总是一样的。但我想随机播放。
但如果它们都通过转换连接,我想这是不可能的,因为转换构成了路径。
并且使用动画组件不适用于 mixamo 动画。由于在动画组件中动画必须是传统类型,但在动画器中它们必须是人形类型并且要正确播放动画,我需要将它们设置为人形类型,这就是我使用动画器而不是动画的原因。播放它们效果很好,但我想按随机顺序播放它们。
【问题讨论】:
我有 12 个状态,它们都通过循环中的转换连接。 所以演奏的流程总是一样的。但我想随机播放。
但如果它们都通过转换连接,我想这是不可能的,因为转换构成了路径。
并且使用动画组件不适用于 mixamo 动画。由于在动画组件中动画必须是传统类型,但在动画器中它们必须是人形类型并且要正确播放动画,我需要将它们设置为人形类型,这就是我使用动画器而不是动画的原因。播放它们效果很好,但我想按随机顺序播放它们。
【问题讨论】:
private AnimationClip[] clips;
private Animator animator;
private void Awake()
{
// Get the animator component
animator = GetComponent<Animator>();
// Get all available clips
clips = animator.runtimeAnimatorController.animationClips;
}
现在你有了所有的动画。
现在有多种方法可以随机化它们...我向您展示最简单的一种,它只是随机选择一个索引并播放该动画。
首先,您将使用一个协程,以便从头开始
private void Start()
{
StartCoroutine (PlayRandomly);
}
在协程中选择一个随机索引并在动画器中播放状态
private IEnumerator PlayRandomly ()
{
while(true)
{
var randInd = Randome.Range(0, Clips.length);
var randClip = clips[randInd];
animator.Play(randClip.name);
// Wait until animation finished than pick the next one
yield return new WaitForSeconds(randClip.length);
}
}
请注意,这是最简单的方法,不能保证“不要在另一个之后播放相同的动画两次”或“在重复之前先播放所有动画”之类的内容
要实现这些,您可以改组剪辑列表,遍历它们并在最后一个剪辑之后再次随机播放等,例如喜欢
private IEnumerator PlayRandomly ()
{
var clipList = clips.ToList();
while(true)
{
clipList.Shuffle();
foreach(var randClip in clipList)
{
animator.Play(randClip.name);
yield return new WaitForSeconds(randClip.length);
}
}
}
public static class IListExtensions
{
/// <summary>
/// Shuffles the element order of the specified list.
/// </summary>
public static void Shuffle<T>(this IList<T> ts) {
var count = ts.Count;
var last = count - 1;
for (var i = 0; i < last; ++i) {
var r = UnityEngine.Random.Range(i, count);
var tmp = ts[i];
ts[i] = ts[r];
ts[r] = tmp;
}
}
}
【讨论】:
. 连接来获得子状态。但我很确定您不应该在 StateName 中有空格,然后 .. 看起来像 @ 987654327@
runtimeAnimatorController 似乎无法知道一个状态是只有一个剪辑还是一个子状态机.. 不确定但 animationClips 可能也已经包含子状态机的剪辑,因此您可以通过 orser 中的州名称过滤列表以仅获取这些剪辑。