Migrating to 4.9: UnrealHeader Tool fails at a UPROPERTY(BlueprintReadWrite) of TArray

Hi there!

So, I had to spend a few long months away from my project (based on 4.8 at the moment).
First thing I try to do when I came back is switching to Unreal Engine 4.9, and it blew up on me.

UnrealHeaderTool choked on my headers. I have several UObject or AActor classes that have arrays of weak pointers, exposed to blueprints at a property. pointers are weak to avoid reference cycles

This worked for me at 4.8, but fails for 4.9: the error I get is Type ‘TArray’ is not supported by blueprint. This seem to mean that Blueprint system won’t accept an array of weak pointers anymore.

  • Switching to arrays of raw pointers is not an option because of reference cycles
  • dropping exposure to blue prints is not an option either, as I am setting several relationships at the editor, and using them in blueprint code

Does anybody know how I can go about this?

_
_
_

Technical Details:

My affected classes look like:

UCLASS(Blueprintable)
class MY_API UMyClass : public UMyParent 
{
  GENERATED_UCLASS_BODY()

  //UnrealHeaderTool fails for this
  UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Blah)
  TArray< TWeakObjectPtr<AMyActor> > Actors;

  //rest of the class
}

The error I get looks like:

F:/path/to/MyClass.h(19) : Type 'TArray' is not supported by blueprint. MyClass.Actors

UnrealHeaderTool seems to work if I change to a TArray of raw pointers. i.e.:

  //UnrealHeaderTool can handle this, but I don't want to leave weak pointers
  UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Blah)
  TArray< AMyActor * > Actors;

  //UnrealHeaderTool can handle this but breaks my maps
  UPROPERTY()
  TArray< TWeakObjectPtr<AMyActor> > Actors;

But I can’t use it.

[Edited syntax for readability]

[Edit II: ]
when I wrote “breaks my maps”, I meant “breaks my blueprints”. My Level Blueprints are just one more thing that breaks. Silly me.

Then prevent cycle referencing in other way, for example make AMyActor inform AMyClass that it’s about to be destroyed by overriding Destroyed():

and make AMyClass remove that actor from array. If you think about it, you will end up with dead weak pointers in array anyway.

This doesn’t work in my case. When I tried it, many objects won’t get destroyed because of the aforementioned reference cycle (thus, implementing Destroyed() didn’t help)

Dead weak pointers were never an issue because I always checked if they were valid.

What aforementioned reference cycle? when you delete item from array it is not exist in memory anymore, there is not invalid or valid pointer, there no pointer at all, there for reference don’t exist. UE4 is full of cycle references (for example Pawn knows which Controller possessing it and Controller knows what Pawn it is possessing), and none of them use weak pointers they clean after themselves (or possibly via UPROPERTY() becuase it also involved with GC). Btw on UObjects pointers, you can use IsValidLowLevel

“Aforementioned Reference Cycle” is the cycle I get when I do not use Weak Pointers in my previous code, as explained in my question. This reference cycle prevents items from being garbage collected, thus they are not destroyed. That’s why I originally did as in the documentation

When I use weak pointers, there is no reference cycle, therefore objects get destroyed, therefore weak pointers got invalidated, and that’s when I removed them. This statement is contingent upon there being no reference cycles.

As to the pawn and controller case, their cycle is broken at the actor’s EndPlay(), that calls the Pawn’s EndPlay(), that detaches from the controller. They don’t have an issue because each pawn has the life cycle of the actor.

Which is not my case.

Ah you use UObject on UMyClass, then you have BeginDestroy()

Again i never seen weak pointer or shared pointer used on UObjects i only see them outside of UObjects and Slate is full of them, and as i know UPROPERTY() is enough for GC to be aware of refrence

BeginDestroy() doesn’t get called either, because the Garbage collector doesn’t go through reference cycles.

I use WeakPointers on both UObjects and AActors, as stated in my question. If you want to see an example from Epic, you can search for TWeakObjectPtr in Strategy Game Example. I do similar things in my code.

As a side note: I don’t want to call Destroy methods by hand, I want the GC to order object termination

: (

But you break the reference, actors gonna be destroyed either way with world. If you don’t need object anymore you destroy it

What is function of that class and why you want it to be GC insted of destroying it when needed? Keep in mind GC do cleaning only once a minute.

Maybe move your UObject to AInfo where you have AGameMode and APlayerController. btw thanks to you i know understand why they are actors

Have your tried to implement a weak ref struct? A struct that contains only a single weak reference property.