+3
Will Not Fix

Wait while coroutine not stopping on state switch Bolt1

Pradeep Kumar 2 months ago updated by Lazlo Bonin (Lead Developer) 1 month ago 5

Upon switching the state the wait while does not seem to be killed.

Unit Graph of PlayVO


Snippet of State Graph


The wait while seems to fire even after the state has exited causing the sequence to continue even if the game state has changed

Bolt Version:
1.4.9
Unity Version:
2018.2.20f1
Platform(s):
Mac Editor, Windows Editor
Scripting Backend:
Mono
.NET Version (API Compatibility Level):
Other
GOOD, I'M SATISFIED
Satisfaction mark by Pradeep Kumar 1 month ago
+1
Pending Review

Hi Pradeep,

Thanks for the report, I'll try reproducing here and let you know my findings.

Hey @Lazio,

I just wanted to share an observation. I see this happen when we use one of our custom units, parallel in the graph. It is based on a suggestion in this thread's comment section, https://support.ludiq.io/communities/5/topics/2244-sequence-behaviour-from-13-instead-of-14.

Below is our custom unit.
Parallel.cs

Hey,

I am attaching a state machine asset to help you reproduce the issue.
The machine will switch state after 3 sec but the wait from the previous state will continue to trigger their logs.

FSM
BugTest.asset

Note* Please make sure the custom unit I have shared above is in your test project.


Working on Fix

Hi Pradeep,

Thanks for the thorough bug report and example files, I really appreciate it. It helps speed things up.

I was able to reproduce the issue and I'm looking into it now. Normally the coroutine should not return any further instructions after having been exited.

+1
Will Not Fix

Hi Pradeep,

After a thorough investigation, I figured that the issue was stemming from your custom Parallel unit. Bolt behaves correctly if you don't use it.

The problem is that when you start one coroutine per output in Parallel.EnterCoroutine, you don't pass the coroutine registry from the current flow as the second parameter. Therefore, when the parent state exits, Bolt is unable to forcibly stop your active coroutines, because it has no reference to them.

The fix would be to replace the line with:

Flow.New(reference).StartCoroutine(output, flow.activeCoroutinesRegistry);

However, Flow.activeCoroutinesRegistry is not a public property, because it's meant for internal implementation only. I will not make it public, because in future versions of Bolt 2, the field was removed. You could use reflection to fetch the field for the time being.

The full workaround would look something like:

        private IEnumerator EnterCoroutine(Flow flow)
        {
            var reference = flow.stack.ToReference();

            var registry = (ICollection<Flow>)typeof(Flow).GetField("activeCoroutinesRegistry", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(flow);

            foreach (var output in multiOutputs)
            {
                Flow.New(reference).StartCoroutine(output, registry);
            }

            yield break;
        }

Note that in Bolt 2, the new Coroutine unit will give you more flexibility, and allow you to start multiple coroutines at once, not necessarily at the start of an event, so there will be no need for your Parallel custom unit.