NewObject<> create from TSubclassOf

I need to pass TSubclassOf as argument to create new object of some type

TSubclassOf<ParentClass> classof = ClassB::StaticClass();
ParentClass* item = NewObject<ParentClass>(this, classof->GetFName(), RF_NoFlags, classof->GetDefaultObject());

But sadly when i create object like this it doesn’t become the one i need. It derives overrided methods, but it doesn’t launch constructor and also when i try to manually call functions that emplaces Constructor, it doesn’t work and it doesn’t work correctly

It prints ID as: “ParentClass”, not as “ClassB” (ID is FString parameter that i change in constructor)
But also when i use it, it prints: Item Used, as if it’s ClassB instance, cuz ParentClass donesn’t print it.
Trying to manually change ID doesn’t result anything.
ParentClass is derived from UObject and is UCLASS(), ClassB is derived from ParentClass.(Just to clearify)

So how can i use TSubclassOf to create new instance of object, if i can’t know what class it will be?

You might want to use NewObject<>(UObject Outer, UClass Class,…)** method wich takes Static Class as second argument, like this:

NewObject<ParentClass>(this, classof->StaticClass());

Or, if your ClassB available in code, you might just go

NewObject<ParentClass>(this, ClassB::StaticClass());
5 Likes

Both methods are causing engine to crash. Both times error is: Assertion failed: Child->IsChildOf(Parent) [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectGlobals.cpp] [Line: 3121] NewObject called with invalid class, Class must be a child of Item
Child object is 100% is child of Item class, so idk why.

1 Like

Okay i got it. Your answer is right, im just failing TSubclassOf initialization idk why. My TSubclassOf doesn’t store Static Class idk why. But in everything else it works great! Thanks for answering!

Thanks to Noowai for answer, i figured out a way to make it all work

    TSubclassOf<UItem> item_class = UItemB::StaticClass();
    UItem* item = NewObject<UItem>(this, item_class);

This is right way to create it, because TSubclassOf contains Static Class pointer in itself, so you just need to pass it as a variable!

4 Likes

Yes, i figured it out, it works now! Big thanks!

I don’t know how you using it, but TSubclassOf<UMyBaseClass> is generally being set via blueprints and data tables. You can do this with an exposed variable (for example UPROPERTY(EditAnywhere)). It gives you an opportunity to specify exact class which it would hold and limit selection to only children of UMyBaseClass.

This is very useful in code to spawn blueprint classes derived from c++ classes. But if you need to spawn pure c++ class you can just use StaticClass() method of class you want to spawn

Thanks you guys! I can’t tell you how long I was stuck on this, my code works now! :slight_smile:

Just a FYI for others, you need to #include Item.h or whatever the file for UItem is, in the file you’re doing the NewObject. Else it won’t compile and the compile error message isn’t very clear on what is going wrong.

I was receiving the same error as OP (Assertion failed: Child->IsChildOf(Parent)) and I found another way of instantiating objects which worked fine.

Not working: NewObject<UBaseClass>(this, VariableContainingSubclass->StaticClass());
Working: NewObject<UBaseClass>(GetTransientPackage(), VariableContainingSubclass);

Could somebody please explain why the second way works fine? Is it somehow connected to the fact the I wanted to construct an object based on abstract UObject?

3 Likes

Not sure why it works, but to my understanding GetTransientPackage() is used for temporary objects so I don’t recommend that.

For anyone who wants to use a CORRECT solution, here is an example:

  • this will work for any native C++ class picked in your BP calling ‘CreateItem’, function from static library, this should also work for any blueprint derived class from your C++ base.

Hierarchy:
UItemBase - base C++ class
UItemWeapon - native C++ derived from UItemBasic

UItemBase* UItemUtilityLibrary::CreateItem(TSubclassOf<UItemBase> itemClass, UObject* owner, const FName& id, int32 quantity)
{
	UClass* typeClass = itemClass;	// implicit conversion into original UClass, see in debugger
	UItemBase* item = NewObject<UItemBase>(owner, typeClass);
	item->Id = id;
	item->Quantity = quantity;
	return item;
}

image

3 Likes