Spawn actor returns null

Hello i’m trying to spawn a custom actor from a blueprint asset reference, but when I call SpawnActor it always returns null.
Here’s the code:

AInventoryItem* UGameLibrary::CreateItem(int32 id, const TArray<FString>& SetupData, UObject* owner)
{
	FItemData data;
	if (GetItemDataFromTable(id, data))
	{
		UWorld* World = owner->GetWorld();
		if (World)
		{

			AInventoryItem* bp = (AInventoryItem*)StaticLoadAsset(FName(*data.BlueprintPath), UBlueprint::StaticClass());
			if (bp) 
			{
				AInventoryItem* item = World->SpawnActor<AInventoryItem>(bp->GetClass()); //World->SpawnActor<AInventoryItem>(bp->GetClass());
				if(item) item->Setup(id, SetupData);
				else GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "Couldn't spawn asset");
				return item;
			}
			else
				GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "Asset not valid: " + data.BlueprintPath);
		}
	}
	else
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "ERROR: Failed to create item");
	return nullptr;
}

I have the pretty same problem on UE 4.12.4. However, MyCustomClass::StaticClass() is not NULL.

The problem is because you’re using UBlueprint.

bp->GetClass() will return UBlueprint::StaticClass(), to get the InventoryItem class you need to make sure the blueprint is compiled (use Kismet blueprint library to compile a blueprint) and then you use the generated class to spawn the actor. But, I don’t think you want to do that because from the name of the function I assume this is not an editor module. You should never use UBlueprint in gameplay/runtime code, blueprint should only exists in the editor, when you publish the game they are not cooked.

So, the solution is to modify FItemData, change the BlueprintPath property that stores path to a blueprint asset to InventoryItemClass that will store path to a class asset :

struct FItemClass
{
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Item", meta=(MetaClass="InventoryItem", AllowAbstract="False"))
    FStringClassReference InventoryItemClass;
};

To get the path to a blueprint generated class just add .[BlueprintName]_C at the end of the blueprint package name, for example if your blueprint’s package name is: /Game/Item/Blueprint/BP_Knife then the class path would be /Game/Item/Blueprint/BP_Knife.BP_Knife_C.

You can always store the class path as FString but FStringClassReference has many useful functions that an FString does not have for example If you’re exposing this data structure in a details panel, unreal editor will display the property as a drop down menu that contains only non-abstract InventoryItem classes (so that user won’t accidentally choose an abstract actor class that would cause an error when it is used as a class for spawning)

And then, assuming that you have modified FItemData to what I have suggested above, change your function at line 10 to something like this:

UClass* InventoryItemClass = data.InventoryItemClass.ResolveClass();
if ( !InventoryItemClass )
{
    InventoryItemClass = data.InventoryItemClass.TryLoadClass();
}

if ( InventoryItemClass )
{
    AInventoryItem* Item = World->SpawnActor<AInventoryItem>( InventoryItemClass )
   ...