Do Delay Units only work in Flow Machines?

alex oatridge 4 years ago updated by Lazlo Bonin (Lead Developer) 4 years ago 12

Delay Units seem to only work in Flow Machines. When places in State Machine it never returns to finish.

In a Flow Machine the console outputs before and after.

In a State Machine only the first console outputs string.

Bolt Version:
Unity Version:
Scripting Backend:
.NET Version (API Compatibility Level):
Pending Review

They should work, if they don't then this is a bug.

Are you only having problems with the next frame unit or all wait units?

Cannot Reproduce

Just tested here, cannot reproduce. That graph works inside a state. Which Bolt version are you using? 

My specs are:
Mac High Sierra
Unity 2017.1.1f1

I found the issue in the last version of Bolt and then upgraded to the 1.1.3 to see the same results.
I am waiting on a fix for a bug I reported related to right-clicking on Mac and self-transitions before I start using 1.1.3 officially and upgrade Unity to the newest version.
None of the Delay Units work for me in States. I have not tried using them in the State Transition but in the State Graph itself.

Update: I created a new project using Unity 1017.2.0 and Delay Units worked. Going to do some poking on my current build to see if I can get it to work there as well.

I reset my app back to the original state with Unity 2017.1.1f1 and Bolt 1.1.2.

After lots of testing, I have found the root of the issue. It seems to be related to the load scene unity and objects set to not destroy. Using my original project I created two new empty scenes.

In scene one I created a single object called GameController with one state.

The first state in this object has a don't destroy on load unit, a simple next frame delay unit and a load scene unit.

The second state has a simple next frame delay unit.

When the game runs, the game object is marked as do not destroy and I get the same results as I first reported. The second untouched scene loads as expected.

The reason I want a delay when the second scene loads are so I can check if certain objects are instantiated before I start the game for the user.

If I bypass the first wait in the first state, the second one works as expected.

This is odd because my original gamecontroller only has one delay unit but many events.

Working on Fix

I see, I think the problem is that coroutines are run on a CoroutineRunner singleton that gets created at runtime. This singleton is not set to DontDestroyOnLoad, so if you load another scene in the mean time, the coroutine behind the wait unit gets cancelled. I'll set the CoroutineRunner singleton to be persistent across scenes in the next version, it should fix it.

However that might not be the issue here, depending on how your transition between these two states is setup. If it's set to run on Update, it means you'll be in the second state before you even load the scene in the first state. Wait unit coroutines are tricky like that, because they run in parallel.

Why do you need to wait 1 frame

The logic behind my thinking is that in the past I have loaded a scene and was not able to access components right away as they have not been instantiated yet. I want to load the next scene and send the logic to the next state that checks if the scene objects are ready to be accessed. If it's not ready, it would wait for a frame and try again in the next iteration. Once the object is found it would trigger a scene ready event that would pass it to a new state.
Maybe just using a state engine covers that for me if each transition is a new frame?

Scene loading in Unity takes 1 frame. You shouldn't need 2 next frame units, only one. What happens if you set up your transition to be the graph that contains the wait unit, and remove them from the states?

I can do that but still looks like I cant apply it till the change is done to the Delay Unit.

State one now looks like this and is waiting for a click event from the player to start the scene.

The state transition now accepts the even and has the wait for frame unit.

The last state has a log unity that prints out loaded.

After the change mentioned above, this would work.

Fixed in Alpha

I made the coroutine runner persistent (DontDestroyOnLoad) for next version. Let's see then if it works!