As of 4.16, if you have a simple class like such:
UCLASS(Blueprintable)
class UMyBlueprintObject : public UObject
{
GENERATED_BODY()
public:
UMyBlueprintObject();
UFUCTION(BlueprintImplementableEvent, Category = "Foo")
void Bar() const;
};
Create a blueprint version that adds logic to the Bar event (even a simple PrintString), and then simply call the event on the CDO (either through another blueprint or simply grabbing it through C++) of that new Object:
TSubClassOf<UMyBlueprintObj> MyDerivedClass; // Set this in the editor or what not.
MyDerivedClass->GetDefaultObject->Bar();
Youâll get the following error:
Ensure condition failed: PointerToUberGraphFrame->RawPointer [File:D:_perforce\Vendor\UE\UnrealEngine-4.16.0-release\Engine\Source\Runtime\Engine\Private\BlueprintGeneratedClass.cpp] [Line: 1094]
Which comes from this method:
uint8* UBlueprintGeneratedClass::GetPersistentUberGraphFrame(UObject* Obj, UFunction* FuncToCheck) const
{
if (Obj && UsePersistentUberGraphFrame() && UberGraphFramePointerProperty && UberGraphFunction)
{
if (UberGraphFunction == FuncToCheck)
{
FPointerToUberGraphFrame* PointerToUberGraphFrame = UberGraphFramePointerProperty->ContainerPtrToValuePtr<FPointerToUberGraphFrame>(Obj);
checkSlow(PointerToUberGraphFrame);
ensure(PointerToUberGraphFrame->RawPointer); // <- Crash due to assert
return PointerToUberGraphFrame->RawPointer;
}
}
UClass* ParentClass = GetSuperClass();
checkSlow(ParentClass);
return ParentClass->GetPersistentUberGraphFrame(Obj, FuncToCheck);
}
That seems to be related to this change that came in from Fortnite:
void UBlueprintGeneratedClass::CreatePersistentUberGraphFrame(UObject* Obj, bool bCreateOnlyIfEmpty, bool bSkipSuperClass, UClass* OldClass) const
{
if (Obj && Obj->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) // <- Added in 4.16
{
return; // <- No Persistent Uber Graph Frame is created for CDOs.
}
Change 3238782 on 2016/12/16 by Ben.Zeigler (Integrated into mainline with 4.16)
#jira FORT-34825 Fix issue where Macro CDOs had corrupted persistent ubergraph frames during blueprint compile on load, by changing it so no CDOs have persistent frames.
This also saves memory as using persistent frames is incorrect for CDOs, things like latent functions do not make sense.
Fix from O'Connor
Removing that added logic fixes the functionality that existed pre-4.16. Is there another way to manually allow a CDO to call overridden script methods?
CDOs are a convenient way to basically enforce a Singleton-esque pattern and keep down memory usage. If blueprint events are no longer allowed on CDOs - then thatâs going to increase memory usage as all objects with blueprint events will now have to be instantiated so they can get their PersistantUberGraphFrame.
Cheers,