StateTreeTasks sometimes don't deserialize correctly

StateTreeTasks implemented by blueprints sometimes don’t deserialize UStateTreeTaskBlueprintBase properties. I tested this with bConsideredForCompletion toggle and debugged the location where the properties get lost.

For some tasks, when I toggle the “+” icon of such state tree task, compile it and save, after the editor is restarted, it has a default untoggled value. The property is correctly serialized (the copy serialized via EditorData), I verified it via ImHex directly within the uasset.

I believe that the deserialization itself takes place correctly, but after that, in ConditionalUpdateNodeInstanceData(), the task is sometimes recreated and some properties are not carried over. The reason for this recreation (that happened to me) is that the task class has prefix “REINST_”. I’m not sure when and why this happens, but I believe no matter the reason, there is a bug in the recreation process.

The issue happens within the RetainProperties function (called from the above mentioned ConditionalUpdateNodeInstanceData). When GetNodeData is called on the old node, the InstanceObject member of the original EditorNode is captured in the FNodeStructView InstanceData member of FNodeRetainPropertyData. However, the PrivateClass of this InstanceObject is UBlueprintGeneratedClass, even though the C++ class itself is UStateTreeTaskBlueprintBase. Because of that, when CopyPropertyValues(OldNodeData.InstanceData, NewNodeData.InstanceData) is called, only the properties of the blueprint itself are iterated and copied, and the direct members of UStateTreeTaskBlueprintBase and UStateTreeNodeBlueprintBase are left at default values.

I’m sorry I cannot provide exact reproduction steps, since I haven’t discovered the reason for the recreation of the task after deserialization. However, I hope I provided enough info for this issue to be resolvable.

[Attachment Removed]

What engine version are you seeing this happen? Does it happen with the same task routinely? How often have you seen this particular deserialization issue?

-James

[Attachment Removed]

Can you try out a small change for me? I am having difficulties in making this repro locally, but I think I may have found something that could be the cause of the break.

If you change the UnwantedFlags line in the method CopyPropertyValues in the file StateTreeEditorNodeUtils.cpp from

constexpr uint64 UnwantedFlags = CPF_DisableEditOnInstance | CPF_EditConst;to

constexpr uint64 UnwantedFlags = CPF_EditConst;. Can you try that change and see if you still see the behavior of the data being reset? Also, is the data fully reset when this happens or does a restart of the editor without saving the change correct the flag to what it should be?

-James

[Attachment Removed]

Thank you for the fix suggestion.

In the meantime, we merged up to version 53676313 and I can no longer reproduce the problem, I just fund that out. There were some changes in functions ConditionalUpdateNodeInstanceData() and GetNodeData() (among many others), so I suppose this could have been directly / indirectly fixed?

I wanted to try your fix on the older version where used to be able to reproduce it, but I’m unable to reproduce it again. I don’t understand how is that possible, maybe there is a difference in the data that UGS doesn’t properly revert to? Other people from our company also cannot reproduce it, even though we weren’t changing or working with the problematic files since then, as far as I know.

The issue was always happening only after editor restart. When I switched the bool through editor UI, it was working properly, until I saved it and restarted editor. Then, during starting the editor, it was first deserialized correctly and shortly after that ConditionalUpdateNodeInstanceData() was called and messed up the properties.

I’m content that everything seems to work now, but I’m sorry that I cannot provide you with more information in order to discover what that issue was and to make sure it is truly fixed.

[Attachment Removed]

I am glad to hear you aren’t experiencing this anymore. I had remembered from previous interactions with the studio that you pulled from Main, but was unsure of where you were on the branch. I am hopeful it has simply been solved in other work that we have been doing. If you do bump into it again, please let us know as it is certainly not something we want to see happening.

-James

[Attachment Removed]

I have been testing this on perforce revision 49673189, and today reproduced it on 51477214 as well.

The problem is not bound to the state tree task only, but to its occurrence within a specific state tree. When it happens, it happens every time and for everybody who downloads the state tree via UGS.

I tried to delete every other state and task except the problematic one from the state tree and then manually recreate an exact separate copy of the tree from scratch. The original simplified tree was problematic 100% of times and the new copy was 100% times working fine. As stated, I wasn’t able to figure out why the REINST_ prefix is added to the instance.

This “corruption” is currently present in 3 of our ~100 trees.

I can try to send this minimalistic version of the tree but I’m not sure whether it would trigger the bug when sent like this.

However I believe that the REINST_ prefix occurrence in some state tree task instances is not the actual issue. I believe the ConditionalUpdateNodeInstanceData() function has the bug no matter what. Any time it is run, it doesn’t copy all the properties.

[Attachment Removed]