StateTree Linked Assets and Property Binding

The default setting and expectation for tasks is bShouldCopyBoundPropertiesOnTick=true, so you expect changes to output properties in a parent state to be ‘seen’ downstream from that task next tick.

It seems that the issue is that the “Parameters” of the linked asset do not appear to have their bindings updated on tick, as you would see if it weren’t a linked asset. This seems like a situation where it is unexpected for property binding to behave differently.

In the screenshot, I’m running an EQS query at intervals, and it invokes an ST_Move_Shared external asset to perform the actual move.

I have verified through the visual logger and debug printing that the EQS query is accounting for the dynamically moving target, meaning the EQS.EQSResult binding to the parameters of this linked asset should be getting updated often, however the change doesn’t get copied across the linked asset parameter boundary during the tick, only the first time the linked tree activates.

As a user, the expectation is that there would be consistency in the copying of properties on tick, even across linked assets.

TStateTreePropertyRef seems to function as a workaround for this problem, but it’s not super convenient to have to use that for every parameter in a linked asset, so it isn’t really broadly applicable.

[Image Removed]

[Attachment Removed]

Ok, so it’s not as bad of a bug as I thought, but still a bug, I think.

The good news is that tick parameter binding does seem to be updated on tick across linked assets, from the Outer LinkedAsset state tree node into the inner state tree GlobalParameters.

The problem/bug seems to be related to instanced bag parameter to instanced bag parameter binding within the linked state tree.

You can create parameters basically on any state within a state tree.

Because I had made the ST_Move_Shared by transplanting a chunk of state tree from when it used to be an internal state tree, the root node in ST_Move_Shared had a bunch of parameters set up for it. These parameters were bound to the global state tree parameters, and then the move task was bound to these parameters, not on the global parameter set, but on parameters of the root state.

So bindings wise, I would have expected it to work, even though there was an extra level of property binding that was unnecessary that was a remnant of transplanting the state tree snippet into a standalone asset.

How it was(using the initial attached image)

  • MoveToAttack - MoveTarget, bound to RunEQS.EQSResult
  • Within ST_Move_Shared
    • Global Parameters(seem to be properly updated on tick from the state tree above)
    • Root State - defined a bunch of parameters on the node itself, all of them bound to the global parameters. These bindings amount to copying state per tick from the assets GlobalProperties property bag, to the property bag on the state node.
    • AI_MoveTo Task, on the root node, was bound to the parameters of the root state, not the global parameters. This meant that per tick, the bindings would have to be
    • RunEQSQuery Task -> MoveTarget(Of linked asset ST_Move_Shared) -> Root Node(MoveComposite) parameter set -> Root Node Task(AI_MoveTo)
    • where it can be simplified as such
    • RunEQSQuery Task -> MoveTarget(Of linked asset ST_Move_Shared) -> Root Node Task(AI_MoveTo)(bound directly to global properties)

Hope that makes sense.

So while logically, I would expect this property binding chain to function, there is certainly an unnecessary added level of property binding in the chain.

Removing this unnecessary level of binding seems to fix the issue and get proper tick property binding working, so I suppose the bug in this situation is that while the GlobalProperties may be updated on tick from the outer state tree, the root state within the linked asset doesn’t seem to have its instanced property bag bindings copied from the GlobalProperties on tick.

This parameter section was in effect an unnecessary level of property binding, and this is where the breakage occurred, presumably between the global parameters and parameters of this state.

[Image Removed]

[Attachment Removed]

You are 100% correct that this is confusing and not how many predict StateTree property binding to behave in this situation. It is something we have been having lots of discussions around internally. The issue boils down to State parameters NOT being updated each tick. The state parameters are updated on EnterState & ExitState. We have not come to a firm conclusion of how we want it to behave between how it works now vs. expected. There are more discussions around this planned for when Epic returns from its winter break.

-James

[Attachment Removed]