简体   繁体   English

Unity3D:何时评估转换条件

[英]Unity3D: When are transition conditions evaluated

I have a very simple game running in Unity, and unfortunately, it is not working as expected. 我有一个非常简单的游戏在Unity运行,不幸的是,它没有按预期工作。

The Context 上下文

I have the following setup: 我有以下设置:

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

From any state, if an integer parameter direction is equal to 1 , set animation player_move_e . 在任何状态下,如果整数参数direction等于1 ,则设置动画player_move_e Same goes for 2 , 3 , 4 for the other directions. 这同样适用于234为其它方向。 Once direction is set to 0 , the idle animation associated with the direction is played. 一旦direction设置为0 ,则播放与方向相关联的空闲动画。

An important thing to point here is, since I am using the "Any State" block, I must make sure that once the animation state changes to one of the move animation states, I reset direction to sentinel value, like -1 , that keeps the animation state in the current state, and not change states to itself again. 这里要指出的重要一点是,由于我使用的是“任何状态”块,我必须确保一旦动画状态更改为其中一个移动动画状态,我就会将direction重置为哨兵值,如-1 ,处于当前状态的动画状态,而不是再次将状态更改为自身。

The Problem 问题

When the player is in the, say, move_n state, and I quickly change the direction to the, say, move_e (not giving it enough time to transition to idle), the animation state is stuck at the move_n :( 当玩家处于,例如, move_n状态,并且我快速将方向更改为,例如, move_e (没有给它足够的时间转换到空闲),动画状态被卡在move_n :(

How can I know if the transition happened, and I am not updating too often? 我怎么知道过渡是否发生了,而且我不经常更新? Initially, I was updating direction in FixedUpdate , and then moved it to Update , but it's the same issue in both methods. 最初,我正在更新FixedUpdate direction ,然后将其移至Update ,但在两种方法中都是相同的问题。

Here is the logic I am seeing: 这是我看到的逻辑:

// 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!
...

UPDATE: 更新:

Here is the whole code: 这是整个代码:

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);
    }
}

I built a small scene for myself and played around a little bit. 我为自己建了一个小场景,玩了一下。 I could reproduce your problem and even found a simple solution. 我可以重现你的问题,甚至找到一个简单的解决方案。

Why it happens 为什么会这样

The problem seems to occur when the animator state machine is still in transition to a new state. 当动画师状态机仍处于转换到新状态时,似乎会出现问题。 During that time, new parameter values are ignored but your code is going to change that value again in the next update() call. 在此期间,将忽略新的参数值,但您的代码将在下一次update()调用中再次更改该值。 The state machine ignored your new direction and now only sees a value for which it has no transition available, direction = -1 for example. 状态机忽略了您的新方向,现在只看到没有可用转换的值,例如direction = -1

The default behavior for transitions is atomic which means according to the reference that it cannot be interrupted. 转换的默认行为是atomic ,这意味着根据引用它不能被中断。 However, setting it to false made no difference... It could be a bug and you may want to file a bug report. 但是,将其设置为false没有任何区别......这可能是一个错误,您可能想要提交错误报告。

Solution

You need to check if the state machine is currently in a transition by checking IsInTransition(int layer) like this: 您需要通过检查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);
    }
}

Another possible solution 另一种可能的解决

I don't know what kind of animations you are using for the different directions, but it may be easier to use one animation and just turn your character around :) This way you have less transitions and states and it may be easier to add more animations later on. 我不知道你在不同的方向上使用了什么样的动画,但是使用一个动画可能更容易,只需转动你的角色:)这样你就可以减少转换和状态,并且可以更容易添加更多动画动画稍后。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM