I had an issue with the game crashing in the cooked game inside of a blueprint code. I have a BP_Parent and BP_Child with the function HandleDeath. The child overrides the parent function and once the child calls the parent method it crashes.
Observations:
It crashes even though the parent HandleDeath function is empty.
The crashes stopped occuring after I disconnect the Parent:HandleDeath node
I made some debugging and found out that FindFunction returns the SKEL_* blueprint in GetMostUpToDateClass. So I’ve tried the following change and it seems to resolve the issue.
[Image Removed]
Did you encounter a similar issue? What do you think of this change (see screenshot)? Is this fix legitimate?
EDIT: It seem to fix a similar PIE issue, so it’s not limited to only cooked game.
Hello! Although I’m glad to hear that that modification unblocks you, the crash you’re experiencing shouldn’t be solved in a CallParentFunction specific way.
I tried out the repro steps you provided but this doesn’t crash on my end. We’ll need more info and a way to reproduce the crash at will to investigate an engine fix. Can you reproduce it at will?
The HandleDeath is on a different object, its the AC_Switch_Enemy component (created in BP). The BP class hierarchy is ActorComponent > AC_Switch > AC_Switch_Enemy. Both of the components share the same owner.
The HandleDeath function is declared on AC_Switch and overriden in AC_Switch_Enemy
The binding is done via CreateEvent node. As an experiment I’ve tried to bind it via CustomEvent which then called HandleDeath, but the result was the same.
Does that answer all the questions?
Thank you for you time. If any question arise, I will try to answer them asap.
Thank you, that info is quite helpful to point the picture. I need a few more details:
Is AC_Switch_Enemy a default subobject of the character actor (AMyCharacter creates it via CreateDefaultSubobject in actor constructor) or is it a SimpleConstructionScript component (BP_MyCharacter adds the component in the component tree)
How about UWhCombatActorComponent?
Who binds AC_Switch_Enemy’s HandleDeath function to UWhCombatActorComponent’s OnCharacterDeath, is it
(a) AC_Switch_Enemy it self via a reference to the WhCombatActorComp?
(b) Or is it the actor that owns both AC_Switch and the WhCAC?
Some workarounds I’d like you to try:
If you’re currently doing the binding directly via event nodes (details panel of a component reference > Events), I’d like you to try is whether binding the event explicitly on BeginPlay. I mean: on BeginPlay, resolve the WhCAC and call [Bind Event to OnCharacterDeath] or [Assign to OnCharacterDeath] in blueprint.
Directly binding via UK2Node_ComponentBoundEvent has historically had some bugs specific to that method of binding.
Recreate the [Parent: Handle Death] nodes by right clicking on the entry node of AC_Switch_Enemy’s Handle Death function graph > Add Call to Parent Function.
What this is meant to rule out is maybe a parent function call node got copied from a sibling blueprint.
[Attachment Removed]
I checked the structure once again and I was wrong about one thing.
The AC_Switch_Enemy is not a component of the actor, but its controller. The Actor has AIController which owns the AC_Switch_Enemy component.
To answer your questions:
1) The AC_Switch_Enemy (child) is added in the component tree (So SimpleConstructionScript it is).
2) UWhCombatActorComponent is created via CreateDefaultSubobject.
3) In the AC_Switch (the parent class) in event graph there is OnPossessedPawnChanged delegate. If the delegate is fired I get a reference to the UWhCombatActorComponent by GetComponentByClass and connect it in this manner: [Image Removed] [Image Removed]
Now that I’m writting it, isn’t the problem that the base class is creating the binding?
About the workarounds:
If I understand it correctly, you are suggesting bind the event directly on BeginPlay. That does not work for me because that is too soon and UWhCAC is not initialized (?). But I think it is similar what you are suggesting but using a diffrent signal (screenshot above).
I’ve tried recreating the “add call to parent function” in the past and it did not change anything.
Thank you. I’ve used the information to try and reproduce your exact setup, but still can’t get the crash to happen. This all is helpful through to converge on what condition is diverging from expectation.
My preference would be to continue comparing until we find out what situation causes the repro, before accepting an engine change that might just conceal a bigger problem. I’ll ask for more info, but I also understand that if at some point you would prefer to just keep your fix/workaround and leave it at that from your side.
The two questions I have currently are:
Is there a dependency from parent BP to child BP? I.e. is AC_Switch_Enemy compiled while AC_Switch is still compiling? Our expectation is that AC_Switch, since its the base class, has finished compiling by the time AC_Switch_Enemy is being compiled so the function here should resolve to the non-skeleton blueprint generated class. You might find a cyclical dependency via my steps here.
Which of the conditions is causing that CallingContext = FBlueprintEditorUtils::GetMostUpToDateClass to be entered here when compiling HandleDeath and the CallParentFunction node in it? I.e. which of the 3 OR conditions is true?
One theoretical scenario where I imagine this issue might happen, is if the child BP (AC_Switch_Enemy) is compiled before its parent (AC_Switch) has finished compiling, which can explain why compilation of AC_Switch_Enemy:HandleDeath accesses a skeleton BP.
Sorry, my focus was something else these few days. I’m motivated to help you figure it out, so that’s not a problem.
To answer your questions:
1) I didn’t find any circular dependecy between the child and parent blueprint, but there might be a cycle formed by AC_Switch by itself.
[Image Removed]There is this AC_NPCGroup which uses the AC_Switch in this manner.
[Image Removed]I didn’t run any further tests as you mention in the linked article, since the class is not a c++ class, but a blueprint (I wouldn’t know where to put the breakpoint). Do you think it would be useful to elaborate more?
2) It was the 3rd condition.
To add more details I can you the whole print. I’ve added this test print:
[Image Removed]Somehow its was called multiple times. The results is
Thanks for those debug logs. That’s very helpful! And thanks for your patience. It took me a while to circle back because I was OOO.
!bBeingCompiled and !IsUpToDate() is an unexpected combination, because if the parent blueprint wasn’t up to date, it should have been flagged for compilation in GatherOutOfDateDependenciesRecursive. Can you print out what the value of BlueprintContext->Status is? I think that will provide the next hint.
That’s very good to know! I believe the parent blueprint having status BS_Dirty while not being flagged for compilation (!bIsBeingCompiled) is the unexpected combination and that might be the problem to investigate further.
I’m passing this case on to my coworker who is more familiar with that part of the BP compiler. Epic is having a company-wide two week break, so we’ll continue investigating on July 6th.