I’ve created a C++ blueprint function library with blueprint implementations of check & ensure. However, one of the features of ensure is that it only reports the failure once by default, which I don’t think I can manage in a C++ blueprint function library. Just like Unreal’s Do Once was implemented in a blueprint macro library, I could implement this in a non-C++ blueprint macro/function library, but doing so lacks several features:
The ability to mark certain pins as “Advanced” and have them collapsed by default
The ability to set category (BPML macros always show up under Utilities, and BPFL functions always show up under their class name)
I see that Unreal has a custom K2Node_DoOnceMultiInput node in its C++ source which I could replicate into a custom Ensure node, retaining the ability to control category/advanced pins while at the same time being able to store state on the node itself. However, looking at its source code, I don’t actually see anything to handle the “do once” part – it’s just code for creating/removing pins / UI, and nothing related to execution. I can’t find the execution implementation that handles only running once anywhere in the C++ source of Unreal.
This is happening in UK2Node_DoOnceMultiInput::ExpandNode. It creates a node of the type UK2Node_TemporaryVariable which is the same as the local boolean node you see in the Do Once macro (the one commented “Is Closed”. Everything else is just versions of the assignments and branches to make it work and the tying of them together.
One alternative (though it’ll sound crazy) is to do your ensure/check as a straight up UFUNCTION, no custom node. You would get your ‘do once’ behavior by keeping a static container (probably TSet though) in the function and tracking the messages that have been tripped. I know it sounds a little crazy, but realistically you don’t want ensures or checks to be tripping anyway so that container should basically always be empty anyway. You’d also run into issues if multiple ensures have the same message, but again the reality shouldn’t be an issue because each ensure should be a unique issue it’s reporting.
To be clear, I was suggesting a static local variable and not a global. But it’s true that the threading issues for those two things are very similar. But also, blueprints don’t/can’t run multi-threaded so it shouldn’t be a real problem. If you’re really, really concerned about it you could always add a mutex. Again, realistically this node should never be getting called in the first place and not at a frequency that any of these things should have a negative impact on your game. And it’s way simpiler to write/maintain than a custom node.