Announcement

Collapse
No announcement yet.

Behavior Tree, Decorator and Level Streaming crash

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Behavior Tree, Decorator and Level Streaming crash

    Engine version 4.9. If you have a behavior tree that calls other behavior trees, and the subtrees have decorators, the decorators are not cleaned up properly on level unload, which results in a crash if the level is reloaded.

    Here's a small repro case.

    Put a single Character Actor on LevelA, with an AIController that starts up a behavior tree (Run Behavior Tree on Event BeginPlay). The behavior tree has a task that invokes another tree, and the subtree has a decorator.

    Main tree:
    Click image for larger version

Name:	BehaviorTree.PNG
Views:	1
Size:	22.7 KB
ID:	1164546
    Sub tree:
    Click image for larger version

Name:	SubBehaviorTree.PNG
Views:	1
Size:	15.0 KB
ID:	1164547

    LevelA, a streaming level, is loaded, then unloaded, then reloaded using the U and L keys:
    Click image for larger version

Name:	LevelLoad.PNG
Views:	1
Size:	114.0 KB
ID:	1164549

    Upon the second load, the following assertion is fired and the runtime is terminated:
    Assertion failed: World->PersistentLevel [File:E:\p4\UE4\Engine\Source\Runtime\Engine\Private\LevelStreaming.cpp] [Line: 390]

    Additional information from the log:

    World exists but PersistentLevel doesn't for /Game/Levels/UEDPIE_0_LevelA, most likely caused by reference to world of unloaded level and GC setting reference to NULL while keeping world object
    External Referencers:
    : (root) UnrealEdEngine /Engine/Transient.UnrealEdEngine_0->PlayWorld
    : World /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default->AISystem
    : AISystem /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default:AISystem_5->BehaviorTreeManager
    : BehaviorTreeManager /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default:BehaviorTreeManager_5->LoadedTemplates
    : BTComposite_Sequence /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default:BehaviorTreeManager_5.BTComposite_Sequence_0->Children
    : BTDecorator_ForceSuccess /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel.CharAIController_C_2.BTComponent.BTDecorator_ForceSuccess_4->Outer
    : (PendingKill) BehaviorTreeComponent /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel.CharAIController_C_2.BTComponent->Outer
    : (PendingKill) CharAIController_C /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel.CharAIController_C_2->Outer
    : (PendingKill) Level /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel->Outer
    : (target) World /Game/Levels/UEDPIE_0_LevelA.LevelA

    Here is the workaround we added to the engine.

    In BehaviorTreeTypes.cpp, change the relevant section of CleanupNodes to:

    Code:
    for (int32 DecoratorIndex = 0; DecoratorIndex < ChildInfo.Decorators.Num(); DecoratorIndex++)
    {
        ChildInfo.Decorators[DecoratorIndex]->CleanupInSubtree(OwnerComp, ChildInfo.Decorators[DecoratorIndex]->GetNodeMemory<uint8>(*this), CleanupType);
        ChildInfo.Decorators[DecoratorIndex] = nullptr; // add this line
    }
    ChildInfo.Decorators.Empty(); // add this line
    In BTTask_RunBehavior.cpp, change the line "while (NodeIt && NodeIt->GetNextNode() != this)" to

    Code:
    while (NodeIt && NodeIt->GetFName().IsValid() && NodeIt->GetNextNode() != this)

    #2
    Originally posted by Pete.Isensee View Post
    Engine version 4.9. If you have a behavior tree that calls other behavior trees, and the subtrees have decorators, the decorators are not cleaned up properly on level unload, which results in a crash if the level is reloaded.

    Here's a small repro case.

    Put a single Character Actor on LevelA, with an AIController that starts up a behavior tree (Run Behavior Tree on Event BeginPlay). The behavior tree has a task that invokes another tree, and the subtree has a decorator.

    Main tree:

    Sub tree:


    LevelA, a streaming level, is loaded, then unloaded, then reloaded using the U and L keys:


    Upon the second load, the following assertion is fired and the runtime is terminated:
    Assertion failed: World->PersistentLevel [File:E:\p4\UE4\Engine\Source\Runtime\Engine\Private\LevelStreaming.cpp] [Line: 390]

    Additional information from the log:

    World exists but PersistentLevel doesn't for /Game/Levels/UEDPIE_0_LevelA, most likely caused by reference to world of unloaded level and GC setting reference to NULL while keeping world object
    External Referencers:
    : (root) UnrealEdEngine /Engine/Transient.UnrealEdEngine_0->PlayWorld
    : World /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default->AISystem
    : AISystem /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default:AISystem_5->BehaviorTreeManager
    : BehaviorTreeManager /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default:BehaviorTreeManager_5->LoadedTemplates
    : BTComposite_Sequence /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default:BehaviorTreeManager_5.BTComposite_Sequence_0->Children
    : BTDecorator_ForceSuccess /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel.CharAIController_C_2.BTComponent.BTDecorator_ForceSuccess_4->Outer
    : (PendingKill) BehaviorTreeComponent /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel.CharAIController_C_2.BTComponent->Outer
    : (PendingKill) CharAIController_C /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel.CharAIController_C_2->Outer
    : (PendingKill) Level /Game/Levels/UEDPIE_0_LevelA.LevelA:PersistentLevel->Outer
    : (target) World /Game/Levels/UEDPIE_0_LevelA.LevelA

    Here is the workaround we added to the engine.

    In BehaviorTreeTypes.cpp, change the relevant section of CleanupNodes to:

    Code:
    for (int32 DecoratorIndex = 0; DecoratorIndex < ChildInfo.Decorators.Num(); DecoratorIndex++)
    {
        ChildInfo.Decorators[DecoratorIndex]->CleanupInSubtree(OwnerComp, ChildInfo.Decorators[DecoratorIndex]->GetNodeMemory<uint8>(*this), CleanupType);
        ChildInfo.Decorators[DecoratorIndex] = nullptr; // add this line
    }
    ChildInfo.Decorators.Empty(); // add this line
    In BTTask_RunBehavior.cpp, change the line "while (NodeIt && NodeIt->GetNextNode() != this)" to

    Code:
    while (NodeIt && NodeIt->GetFName().IsValid() && NodeIt->GetNextNode() != this)
    Hi Pete.Isensee,

    Please post this to the answerhub in the bug reports section (link in signature) so we can assist you more in depth. In your answerhub post, please include what steps you are taking to reproduce this on your end as well as crash logs, callstack, and dxdiag. You can get your crash logs for a crash by going to \Unreal Projects\PROJECTNAME\saved\logs\. Additionally, please let us know if you have attempted this in a clean, blank project with no additional content and whether this reproduces there or if it is limited to an individual project.
    Adam Davis | Marketplace Support | Epic Games
    How to report a bug? | Installation & Setup issues? | Answerhub Bug Reports | Twitter

    Comment


      #3
      Posted at https://answers.unrealengine.com/que...-streamin.html

      Comment

      Working...
      X