Unity3D:何时评估转换条件

时间:2014-04-23 07:10:05

标签: animation graphics unity3d

我在Unity中运行了一个非常简单的游戏,不幸的是,它没有按预期运行。

上下文

我有以下设置:

http://mazyod.com/images/Screenshot_2014-04-23_10.51.20.png

在任何状态下,如果整数参数direction等于1,请设置动画player_move_e。对于其他方向,234也是如此。将direction设置为0后,将播放与该方向关联的空闲动画。

重要的一点是,因为我正在使用"任何国家"阻止,我必须确保一旦动画状态更改为其中一个移动动画状态,我将direction重置为哨兵值,如-1,将动画状态保持在当前状态,而不是再次改变状态。

问题

当玩家处于move_n状态时,我快速将方向更改为move_e(没有给它足够的时间转换到空闲状态),动画状态卡在move_n :(

我如何知道过渡是否发生,而且我不经常更新?最初,我正在更新direction中的FixedUpdate,然后将其移至Update,但这两种方法都存在同样的问题。

以下是我所看到的逻辑:

// MY CODE
animator.SetInteger(1); // Initially, it's move_e
...
// WITHIN UNITY (making it up)
Unity.UpdateStates(); // The number is read in the engine, and transition happens
...
// MY CODE
animator.SetInteger(-1); // Stay at current animation
...
// WITHIN UNITY (making it up)
Unity.UpdateStates(); // The number is read in the engine, nothing should happen
...
// MY CODE
animator.SetInteger(0); // The logic briefly changes to idle
...
// WITHIN UNITY (making it up)
Unity.UpdateStates(); // The number is read in the engine, transition to idle
...
// MY CODE
animator.SetInteger(4); // transition to north
...
// WITHIN UNITY (making it up)
// NOTHING HAPPENS!! It doesn't catch up
...
// MY CODE
animator.SetInteger(-1); // Stay at current state, assuming it changed to move_n
...
// WITHIN UNITY (making it up)
Unity.UpdateStates(); // The number is read in the engine, stays at idle_e!
...

更新

以下是整个代码:

void Update()
{
    // update animator (Stupid transition from any state includes current state -_-")
    int heading = CalculateHeading(horizontalInput, verticalInput);

    if (heading != previousHeading)
    {
        anim.SetInteger("direction", heading);
        previousHeading = heading;
    }
    else
    {
        anim.SetInteger("direction", -heading);
    }
}

void MovementManagement ()
{
    // If there is some axis input...
    if(horizontalInput != 0f || verticalInput != 0f)
    {
        Vector3 position = transform.position;
        position.x += horizontalInput * movementSpeed;
        position.y += verticalInput * movementSpeed;

        transform.position = position;
    }
}

int CalculateHeading(float horizontal, float vertical)
{
    if (horizontal == 0f && vertical == 0f)
    {
        return 0;
    }

    if (Mathf.Abs(horizontal) > Mathf.Abs(vertical))
    {
        return (horizontal > 0 ? 1 : 3);
    }
    else
    {
        return (vertical > 0 ? 4 : 2);
    }
}

1 个答案:

答案 0 :(得分:2)

我为自己建了一个小场景,玩了一下。我可以重现你的问题,甚至找到一个简单的解决方案。

为什么会发生

当动画师状态机仍处于转换到新状态时,似乎会出现问题。在此期间,将忽略新参数值,但您的代码将在下一次update()调用中再次更改该值。状态机忽略了您的新方向,现在只能看到没有可用转换的值,例如direction = -1

转换的默认行为是atomic,这意味着根据reference它不能被中断。但是,将其设置为false没有任何区别......这可能是一个错误,您可能想要提交错误报告。

<强>解决方案

您需要通过检查IsInTransition(int layer)来检查状态机当前是否处于转换状态:

void Update()
{
    // update animator (Stupid transition from any state includes current state -_-")
    int heading = CalculateHeading(horizontalInput, verticalInput);

    if (heading != previousHeading && !anim.IsInTransition(0))  // you may need to adjust the layer index
    {
        anim.SetInteger("direction", heading);
        previousHeading = heading;
    }
    else
    {
        anim.SetInteger("direction", -heading);
    }
}

另一种可能的解决方案

我不知道你在不同的方向使用什么样的动画,但是使用一个动画可能更容易,只需转动你的角色:)这样你就可以减少过渡和状态,并且可能更容易稍后添加更多动画。