End simulation during "Use Claimed Gameplay Behavior Smart Object" Node crashes editor

I have followed the Smart Objects Quick Start tutorial and for the most part it works. However if I exit the simulation after the “Use Claimed Gameplay Behavior Smart Object” node is called and before it completes the editor crashes. If I end the simulation at any other time there is no issue, it’s specifically while the Use Claimed Gameplay Behavior Smart Object node is navigating my AI Actor to a Smart Object.

When the crash occurs the top of the stack trace is:

Assertion failed: OwnerController->GetPawn() [File:D:\build++UE5\Sync\Engine\Plugins\Runtime\GameplayBehaviorSmartObjects\Source\GameplayBehaviorSmartObjectsModule\Private\AI\AITask_UseGameplayBehaviorSmartObject.cpp] [Line: 271]

That line in question is calling a check() function on OwnerController->GetPawn(). I’m assuming the check() function is just an assertion that the input is not null - can anyone tell me whether that assumption is correct?

If so, what then? The controller input to that node is the Owner Controller passed in by the Event Receive Execute AI. I’m not sure there should necessarily be an expectation that the owner controller has a Pawn?

My guess is that there’s something amiss in the configuration of the AI Controller, and I assume that gets configured under the hood by the various Blueprint Classes etc I created during the tutorial. If anyone has any insight into exactly what the GetPawn() is supposed to be referring to and how that relates to my resources I’d appreciate the help.

1 Like

Hey,
I had exacly the same error. The problem is the callback “OnSlotInvalidated”
seems that if it gets called on game destruction the pawn doesn’t exist anymore.

void UAITask_UseGameplayBehaviorSmartObject::OnSlotInvalidated(const FSmartObjectClaimHandle& ClaimHandle, ESmartObjectSlotState State)
{
    // these two lines do the trick. Maybe there is a smarter way ;)
	if(OwnerController == nullptr) return;
	if(OwnerController->GetPawn() == nullptr) return;
	
	Abort();

	EndTask();
}

Hey did you ever figure out a fix for this issue? We’re running into it but haven’t found a fix yet…

Hi, I just had the same issue when I switched unreal version from 5.1 to 5.2. What helped was Reloading all AI-related assets. After that I had to fix some cached things and it started working again.

Hey ! i’m have the same issue, if its possible could u be a bit more detailed on how did u fixed it

1 Like

I’m also having the same issue. If someone could list the steps required to fix this it would be super helpful. :slightly_smiling_face:

1 Like
  1. Go to Epic Games\UE_5.2\Engine\Plugins\Runtime and move the “GameplayBehaviorSmartObjects” to your Plugins project folder.

  2. If you don’t have the Plugins folder, create one in the project root folder.

  3. Go to GameplayBehaviorSmartObjectsModule\Private\AI\AITask_UseGameplayBehaviorSmartObject.cpp - UAITask_UseGameplayBehaviorSmartObject::Abort, comment out check(OwnerController->GetPawn()); and add if (OwnerController->GetPawn()) check before the AbortBehavior.

  4. Do the same in UAITask_UseGameplayBehaviorSmartObject::OnGameplayTaskDeactivated and add a nullptr check on line 204

In case the problem still persists, check your Build.cs and remove “GameplayBehaviorSmartObjectsModule” from the PublicDependencyModuleNames.

With these changes your project should use the custom plugin from the project Plugins folder and the plugin will no longer crash the editor on game stop. However, in case of the plugin updates you have to update it manually until they fix the issue.

5 Likes

thank you for taking the time to answer!

Still having a issue my side can you please explain what i need to do when you say check your build.cs step

It is probably still taking the plugin from the engine folder. Make sure it uses the one in your project. You can even try deleting it from the engine folder to be sure. The error should not happen then. Build.cs could stay as it is.

Just ran into this problem as well. Verified that the plugin is in fact listed in the “PROJECT” node of the plugin list within the editor. Error happens on the same line number, a line that is commented out. So clearly its not using my plugin and using a cache maybe?

Hmmm, I was using a BluePrint project. Make sure you go to “Tools” - “New C++ Class” and create a new dummy file. This will enable C++ for your project. Restart, then it will work and your local plugin will be used.

1 Like

Thanks for noting this. I didn’t test it on a pure blueprint project so that was probably the reason my solution didn’t work also for Panos98.

I think mine may also be related to this? It only seems to happen when they are in a World Partition Level though.

Assertion failed: SmartObjectSubsystem [File:D:\build++UE5\Sync\Engine\Plugins\Runtime\GameplayInteractions\Source\GameplayInteractionsModule\Private\GameplayInteractionContext.cpp] [Line: 121]

UnrealEditor_GameplayInteractionsModule!FGameplayInteractionContext::Deactivate() [D:\build++UE5\Sync\Engine\Plugins\Runtime\GameplayInteractions\Source\GameplayInteractionsModule\Private\GameplayInteractionContext.cpp:121]
UnrealEditor_GameplayInteractionsModule!UAITask_UseGameplayInteraction::OnDestroy() [D:\build++UE5\Sync\Engine\Plugins\Runtime\GameplayInteractions\Source\GameplayInteractionsModule\Private\AI\AITask_UseGameplayInteraction.cpp:195]
UnrealEditor_GameplayInteractionsModule!V::TBaseUObjectMethodDelegateInstance::ExecuteIfSafe() [D:\build++UE5\Sync\Engine\Source\Runtime\Core\Public\Delegates\DelegateInstancesImpl.h:667]
UnrealEditor_SmartObjectsModule!FSmartObjectRuntimeSlot::Release() [D:\build++UE5\Sync\Engine\Plugins\Runtime\SmartObjects\Source\SmartObjectsModule\Private\SmartObjectRuntime.cpp:169]
UnrealEditor_SmartObjectsModule!USmartObjectSubsystem::AbortAll() [D:\build++UE5\Sync\Engine\Plugins\Runtime\SmartObjects\Source\SmartObjectsModule\Private\SmartObjectSubsystem.cpp:640]

Found a way around, you can just use a pre BTT task named FindAndUseGameplayBehaviorSmartObject
just drag it out from from a sequence in the BT

Getting a similar crash in 5.5, only in my case the crash occurs when loading a map inside a world partition level with smart objects. This affects my save/load system since the map gets re-loaded when a save slot is selected.

I did as @mat783 suggested and copied the GameplayBehaviorSmartObjects plugin from the engine folder to my project’s plugins folder.

The code in AITask_UseGameplayBehaviorSmartObject.cpp has changed a bit since his post, so I will just outline the changes I ended up making:

Inside Abort():

void UAITask_UseGameplayBehaviorSmartObject::Abort()
{
	if (MoveToTask)
	{
		// clear before triggering 'the end' so that OnGameplayTaskDeactivated
		// ignores the incoming info about task end
		UAITask_MoveTo* Task = MoveToTask;
		MoveToTask = nullptr;
		Task->ExternalCancel();
	}
	else if (!bBehaviorFinished)
	{
		if (GameplayBehavior != nullptr)
		{
			//check(OwnerController);
			//check(OwnerController->GetPawn());
			if (IsValid(OwnerController) && IsValid(OwnerController->GetPawn()))
			{
				GameplayBehavior->GetOnBehaviorFinishedDelegate().Remove(OnBehaviorFinishedNotifyHandle);
				GameplayBehavior->AbortBehavior(*OwnerController->GetPawn());
			}
		}
	}

	EndTask();
}

Inside OnDestroy():

void UAITask_UseGameplayBehaviorSmartObject::OnDestroy(const bool bInOwnerFinished)
{
	if (ClaimedHandle.IsValid())
	{
		USmartObjectSubsystem* SmartObjectSubsystem = USmartObjectSubsystem::GetCurrent(OwnerController->GetWorld());
		//check(SmartObjectSubsystem);
		if (IsValid(SmartObjectSubsystem))
		{
			SmartObjectSubsystem->MarkSlotAsFree(ClaimedHandle);
            SmartObjectSubsystem->UnregisterSlotInvalidationCallback(ClaimedHandle);
            ClaimedHandle.Invalidate();
		}
	}

	if (TaskState != EGameplayTaskState::Finished)
	{
		if (GameplayBehavior != nullptr && bBehaviorFinished)
		{
			OnSucceeded.Broadcast();
		}
		else
		{
			OnFailed.Broadcast();
		}
	}

	Super::OnDestroy(bInOwnerFinished);
}

No more crashing after these changes :slight_smile: Thanks @mat783 for pointing in the right direction

Hi there everyone!

I think the above solutions would definitely solve the problem (Since you won’t be accessing a null pointer anymore) but I’m not sure that’s the right way to go.
I’d like to pitch an alternate solution that doesn’t involve changing the engine, especially for any of ya’ll using binary versions of Unreal.

The issue likely occurs because at some point in your code you’ve started a Smart Object Gameplay Behavior Task such as “MoveToAndUseSmartObjectWithGameplayBehavior”.

When that task is active (eg. movement in progress) and you close your Play in Editor or Client session that’s when you hit the crash. It’s crashing because it’s attempting to clean up that task but the World it existed in and/or SmartObjectSubsystem have already been cleaned up.

The easy fix is to add blueprint code in the place you spawn the task to end it on Destroy/Exit/Completed.

For example if you spawn a MoveToAndUseSmartObjectWithGameplayBehavior task inside a State Tree Task Blueprint via Event Enter State then make sure you store a reference to it.

Now add Event ExitState to that same Blueprint and call EndTask on the stored task

This cleans up your in-progress task at the right time during shutdown/exit and you won’t hit the crash anymore