Serialized dynamic multicast delegate holds bound references to spatially loaded actors

Hello UDN,

We encountered an issue with a dynamic multicast delegate on a non-spatially loaded (NSL) actor when it is bound by spatially loaded (SL) actors. Specifically, map check gives us errors stating “SL actors referenced by the NSL actor”. The references turned out to be the SL actors who were bound to the NSL’s delegate when the NSL actor was serialized.

In an attempt to avoid these errors, we tried marking the delegates as Transient. This fixed the map check errors, since the delegates no longer serialize the bound NSL references, but it appears to have broken UK2Node_ActorBoundEvent nodes in the level script.

Since making the delegate Transient causes other issues, my question then is what method should we be using to have our SL actors bind to delegates of NSL actors without creating the map check errors?

Thanks

Michael

Steps to Reproduce

Hey there, I can confirm I can reproduce the issue between a NSL and SL actor. I believe this bug is an oversight of the interplay of various systems (world partition and blueprint): (SL) ActorB binding to a delegate of (NSL) ActorA indeed results in a weak reference from ActorA to ActorB. There are ways we can handle this better in engine code, including:

  • Detecting this at level save-time, instead of the time you load the level in editor. At least I observed the map check only starts to error on the next map load, did you see the same?
  • a) Promoting ActorB to become non-spatially loaded since it’s a dependency for ActorA. That would solve this issue, however would that be an acceptable solution to you? Any actor binding to a NSL actor’s delegate would become always loaded.
  • b) Allow ActorB to be loaded later, and when it’s loaded try to resolve ActorA to bind the delegate. This change in how delegates are serialized would involve more work than the other options.

Curious about your thoughts, so I can propose the change to the engine dev teams and at least know that it would improve your situation.

In the meantime, I recommend using this workaround: let the SL actor have a soft object reference to the NSL actor and do the delegate binding on the SL actor’s BeginPlay. I’ll attach a screenshot for reference. I confirmed that saves fine, keeps the SL actor spatially loaded and the soft object reference gets resolved when the SL actor is loaded and works in builds.

Hi Zhi Kang Shao, thanks for the prompt response.

I feel I should clarify our use case more.

We have testing actors that perform queries on our navigation graph. They can generate a path between two points and report metrics for debugging. The use case here is to ensure a path can be generated while editing the level.

Our testing actors are spatially loaded.

The navigation graph actor is non-spatially loaded.

Our testing actors bind to the OnBuild delegate on the nav graph actor, which will broadcast when it has been rebuilt and allow the testing actors to update their paths accordingly. This is the delegate causing the map check errors.

We don’t need the binding of the testing actors function to the nav graph OnBuild delegate to be serialized, since they can rebind themselves when loaded/created.

With this context, to answer your questions

  • Having the warnings appear at save-time would highlight the issue earlier but the issue we’re having is that the SL actors can be legitimately bound at the time the NSL actor is serialized.
  • a) Promoting the SL actor to be NSL is not an option for us as there could be many SL actors which would then be always loaded. They also wouldn’t give valid feedback as while the navigation graph actor is NSL, the graph data it manages is streamed as SL actors meaning most would report back failures due to there being no graph data to test.
  • b) Having more robust delegates able to handle bindings from SL actors as they are loaded would certainly fix this issue. I agree that it does not seem like a simple fix though.

Thank you for looking into the workaround, though we sadly can’t use blueprints for the functionality we need.

We’ve gone for another workaround that splits the delegate logic. We’ve removed our transient fix to get the original behavior that keeps the ActorBoundEvent node working. And for SL actors we’ve added another separate transient delegate so the SL actor references are not saved.

Hey there, thanks for providing answers to the questions I had. I’m glad that you found a workaround by introducing a transient multicast delegate.

I understand promoting those SL actors to NSL is not always an acceptable solution, especially with your use case. I’ll give feedback to the team regarding detecting incompatible binding (NSL binding to SL) resulting in warnings earlier. But since you are unblocked, I’ll close this case - respond here if any questions remain though. Thanks for sharing how you worked around this.

[Image Removed]