Why is my TSoftObjectPtr null even though the actor it should be pointed at is what triggered the check?

I have a Quest c++ class/actor that has a list of “ImportantActors” which are TSoftObjectPtrs that point to actors that are important to different objectives in the quest. I’m having a bug where these pointers will return nullptr even though the check was initiated by the actor that should be what’s referenced in said soft ref. I’m using 4.27.2 and level streaming where the quest is in an ‘always loaded’ level, but I want/need to be able to reference objects in other levels they may be streamed in when they are needed (this actor is for sure streamed in because, as I said, it’s the trigger for the check that I’m making). That’s why I’m using Soft References. This normally only happens when I have gone through the level to this point “failed” triggering this check which then triggers a Open Level to reset the level, and then come back and tried to fail again, but it doesn’t pass the check so it does reset the second time. In the editor when it is happening I’m getting a yellow Warning Icon on that soft reference that says:

Unloaded reference to Actor ID 'blah/path/Triggering_NPC_BP_2', use Browse to load level

But like I said it does work the first time most of the time, so clearly it’s not that it’s not set correctly at least initially, and I don’t have any code that should be changing any of those settings. The point of that property is for the level guy to be able to set up all the connections between level components and the quest structure.

I’m completely lost because I thought this was exactly what soft references were for and seeing as the actor that should be referenced is triggering the check the soft reference to it should be valid and not null I would think…

So I’ve been playing with this and I have figured out that it seems like the Actor’s Full name/path is changing for some reason. So as a visual here is what the trigger actor (path) vs the SoftObjectPtr reference (path2) when things are working:

And then when the bug pops up the paths change to something like this:

What is making those change like that? It’s the actor in the streamed in level that is triggering the event who’s path is changing… why? Is there any way to prevent this or work around it?

I’ve thought of a bit of a workaround, but I would rather do this the right way^^;

Working around it with this for now… Would love to get this working properly at some point…

  auto invoker = ptrToInvokingObject->GetFName().ToString();
  auto soft_ref = soft.GetUniqueID().GetSubPathString();
  if (soft_ref.Contains(invoker)) {
    // verified that the invoker is who we expect it to be for this event, keep going
  }

Now the issue is that I can’t reference the actor to mark it for the objective /sigh

Bugs seem to surround soft pointers, I reported these long ago:

[UE5] TLazyPtr nulls only when travelling to level?

[UE5.2, Bug report] Blueprint soft class pointer broken. reverts to base class.

If soft pointers are not working properly at all, I would probably let actors register themselves to a manager class as “quest relevant” by holding a quest component or something, then instead of using pointers to bind one thing to another I’d use GUIDs which can retrieve a loaded actor from the manager. Manager could be a GameInstanceSubsystem.

1 Like

I was just reading through one of your posts in hope. lol. Thank you for replying!
Hopefully someone from epic chime in, but in the meantime I’ll be thinking through your suggestions. Thanks again!:slight_smile:

1 Like

EPIC has been ignoring every single post of mine :slight_smile: but we have a great community.

1 Like

Yeah, in line with your other posts I’m doing a “Load Asset Blocking” and it’s not finding it. I’ve actually stepped through the engine code and it’s FOR SURE because the package/path of the actor being reference is changing… What I don’t understand is why the package/path is changing like that? And what is the point if the soft ref can’t keep track of that?

Can’t tell, never deep dived into this property type. Maybe it changes to refer to a dupe / instantiation instead of the original similar to how a level is copied for PIE to not affect the original data in the editor. Maybe this makes no sense. I see an addition of “UEDPIE_0” in the changed path. This would suggest other additions are possible too since PIE is “Play In Editor”. Wonder if other modes like standalone misbehave.

This is what made me think of the unsolved issue “TLazyPtr nulls only when travelling to level” where I had set a soft reference from the editor panel, on an actor placed in the level to another actor. The soft property itself nulled for no reason.

  • Have to wake up early tomorrow, will reply when I can later tomorrow.
1 Like

OK, so I can’t seem to reproduce it in a packaged build so maybe that’s a positive? Not sure if it’s because it’s not going to happen or if it’s because I haven’t waved my arms and patted my head in the right way to make it happen… that’s the frustrating thing about bugs like this. May be a PIE bug only?

2 Likes

That might be the case then, it does look like it. Many exceptions are made to make PIE what it is. If we can pin PIE on the issue then we can make more specific searches for reported bugs. Found this one just now:

TSoftObjectPtr points to actor within wrong UWorld when running PIE - #3 by UnexpectedSquirt

1 Like

I can see how that would be the right track, but it doesn’t work out of the box and, since we are on a tight timeline, I haven’t had time to debug it. Will hopefully get some time to debug it and try to get it working this week. Thanks for pointing that out!

I thought I had replied to this, but guess I didn’t. We are about to make the big move to 5.x so I’ll see if this is still an issue after that. If so I’ll post back here with how I fix it^^

1 Like