0
Cannot Fix

Multiple Macro SuperUnits in the same flow use the output of the last

Vong 2 years ago updated by Lazlo Bonin (Lead Developer) 2 years ago 3

Here's a reproduction test case where a macro super unit is used twice in the same flow.

1) attach a flow machine to an empty gameobject
2) make a macro superunit and attach it in the same flow.
3) provide two different gameobject inputs to the two superunit instances.

Notes:
In my simple testing, it seems to happen when a gameobject is the input, fine when int.
As can be seen in the second image, all connections work correctly except for the one leading to Output.
Disconnecting the second instance from the flow immediately reverts the first output to its correct output. 
(edit: also not the Manual Event, forgot to replace, but was initially happening onMouseDown)

The Flow Graph:

In the Flow Graph


In the (first) Super Unit: "Test 2"

Bolt Version:
1.4.0f11
Unity Version:
2018.2.18f1
Platform(s):
Scripting Backend:
.NET Version (API Compatibility Level):
Cannot Fix

That is an edge case with the current design for super units. Their result is not cached, it is fetched dynamically. However, the result of method calls, like Parse, is cached on entry when an entry is connected.

It's kind of hard to explain exactly the order of what happens here, but the fix is simple.

Just remove the control ports in your super unit and let Bolt figure out when to call the value ports automatically. Each value will be dynamically fetched only when needed and you'll get the proper behaviour.

Ick. So there are particular units that don't play well inside of a super unit (in this edge-case..which I'll be using prolifically) and the fix is to omit control flows for that super unit.

Is there a rough guide to discerning these units? (initial case didn't use Parse) or is it coding minutiae that has to be considered case-by-case....

From what I understood from your explanation, I tried an alternate fix in which I cache the output before doing the second super unit. Are the any problems with doing it that way (for cases where I would need control flow)? (though it kinda defeats the whole DRY thing with repetitive Caches but eh)


It's not so much that there are particular units that work differently, it's the overall caching logic that discerns between whether or not you pre-entered the port via a control flow. There's a very good community tutorial explaining this in detail here:

Here's what's basically happening in your case:

  1. Flow enters first Super Unit
  2. Flow reaches Float.Parse
  3. Float.Parse fetches Get Name
  4. Get Name fetches Var
  5. Var returns Self from parent graph
  6. Get Name returns "20"
  7. Float.Parse returns 20 and caches this result in its output (because you specified when to call it by connecting its control input), at the flow level
  8. Flow reaches Output
  9. Flow enters second Super Unit
  10. Flow reaches Float.Parse
  11. Float.Parse fetches Get Name
  12. Get Name fetches Var
  13. Var returns the value of your Scene Variable
  14. Get Name returns "40"
  15. Float.Parse returns 40 and caches this result in its output
  16. Flow reaches Output
  17. Flow reaches String.Concat
  18. Arg 0 fetches Res
  19. Res returns 40, the cached result of Float.Parse
  20. Arg 1 fetches Res
  21. Res also returns 40, the cached result of Float.Parse
  22. String.Concat returns "4040"
  23. Flow reaches Log
  24. Log outputs "4040"

In Bolt 2, we plan to add a "function" mode to Super Units, which would make them behave like traditional C# functions instead of macros (single control input, single control output, value inputs cached on entry, result cached on exit). This would fix the behaviour you're seeing. In the mean time, the workaround is indeed to remove the control ports.

Another possible workaround would be to use a Cache unit right after the first Super Unit so that its result gets cached independently.