Yeah, it’s valid, but I think I know where the problem is.
The problem occurs on RegisterPassive, when this is called:
targetAttribute->RegisterPassive(this);
But I thought that targetAttribute was valid, and it seems it isn’t. Here’s the code I omitted from UBasicPassive::OnInitialize (I thought it wasn’t relevant for this post)
void UBasicPassive::OnInitialize()
{
Super::OnInitialize();
targetEntity = Cast<ABaseEntity>(target->GetOwner());
if (UProperty* prop = targetClass->FindPropertyByName(targetAttributeName))
{
targetAttribute = (UEntityAttribute*)prop->ContainerPtrToValuePtr<UObject>(targetEntity);
if (targetAttribute == nullptr)
{
//Log Error
return;
}
}
else
{
//Log Error
return;
}
targetAttribute->RegisterPassive(this);
}
As you can see, targetAttribute is never null, but it doesn’t mean the pointer is valid. So when I call RegisterPassive, I’m calling it on an invalid object and everything goes to hell. After I did a Cast instead of a C-Style cast, UE4 crashed because the pointer returned by [FONT=courier new]prop->ContainerPtrToValuePtr(targetEntity) wasn’t a [FONT=courier new]UEntityAttribute.
After finding this I could fix the problem, here’s how I get [FONT=courier new]targetAttribute now
if (UObjectProperty* prop = Cast<UObjectProperty>(targetClass->FindPropertyByName(targetAttributeName)))
{
targetAttribute = Cast<UEntityAttribute>(prop->GetObjectPropertyValue_InContainer(targetEntity, 0));
...
Now everything works fine. The issue was caused because the C-Style cast can only fail at compile-time, so if the object isn’t a [FONT=courier new]UEntityAttribute I get no errors but the pointer is invalid.
Ok, lesson learned, always prefer UE4’s Cast function or C++ casts (dynamic_cast, static_cast) over C-Style casting.
Thanks for your help!
(■■■■ I feel stupid)