Why can't we use TArray of TWeakObjectPtr from C++ to blueprint?

Hi,

Consider this kind of code :

UCLASS(Blueprintable)
class GAME_API ACustomActor : public AActor
{
   GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Cat")
	TArray< TWeakObjectPtr<AAnotherSubActor> > listOfStuff;
}

I get a compilation error like this :

error : Type ‘TArray’ is not supported by blueprint.

My goal is to create a blueprint from that Cpp Class, to add meshes and basic logic more easely than writting every thing, and I keep Cpp for more advanced/algorythmic stuff.

Obviously I don’t want to deal with dangling pointer in my arrays, as I allow those arrays to be filled by in blueprint or in the editor. TWeakObjectPtr seamed to be the perfect wrapping class, I could use IsValid() to be sure of the state of my Actors etc.

I guess from the very few other threads talking about that, if I use a TArray< Actor *> it will work, but isn’t it a nightmare to manipulate an array of raw object my class don’t have ownership of and that can be destroyed anywhere else in the engine ?

What would be a better, or at least more common approach in unreal guide lines here ?
Thanks

TWeakObjectPtr type is not supported by reflection system or blueprint itself, this type was made for use outside of it (for example Slate which powers UMG as it complitly outside reflection system). All variables visible to engine with UPROPERTY() are already managed, they will automatically null pointers to all properly deleted UObjects, so no need to use those special pointer types on UPROPERTY() variables (or else some specific container type don’t cooperate with garbage collection, but all blueprint supported type should)

Oh !

That also works for the content of TArrays ?
I mean, if I add some SubActorA into an array that is a UProperty of my SubActorB class (like this TArray)
and then, if the engine or editor or anyone else delete one of the elements of this array without notifying my SubActorB, the element will still be set to null instead of an dungling ptr ?

Sry i was wrong a bit, it does not remove or null the pointer, instead it keeps actor alive in memory until it’s removed, and then you can check IsPandingKill

Bluepritn Array is TArray, so you can experiment via blueprinting how array and object behaves in such case

oki, I’m going to bootstrap a small project to test that behavior.
Having an actor that possess an array of other actors seams to be an extremly common use case into a game, it would be surprising that cpp to blueprint can’t handle that use case.
Thank you for your response

ok I did the test, and you were right it is set to Null. The workflow when actor is destroyed by some action is :

  • Actor Destroyed() is immediately called, and mesh or other visual things immediately disapears
  • At that moment array pointer still point to the valid actor that can be used
  • One minute later, GC come through
  • Actor destructor is called
  • Array is still the same size, but ptr of the concerned array element is NULL

I can then use raw pointers for UObjects at least.

Alright, so i was right after all :slight_smile: sry i only test on blueprint as it a lot easier to test there

I just want to add to this, since I just hit the same issue.

First to clarify, the reflection system does support TWeakObjectPtr, it is specifically the BlueprintReadWrite/Only specifiers that are incompatible,

The behaviour you list here is exactly why I use TWeakObjectPtr extensively (in both UPROPERTY and non-UPROPERTY contexts), especially for actors and components which are different from most UObjects in that they are frequently destroyed directly. By doing so, I never in any of my UE4 coding have cause to mess around with low level functions like IsValid or IsPendingKill, because weak object pointers become invalid the moment an object is marked for kill. Managed raw pointers on the other hand are only cleaned up later when the GC runs, meaning you really need to use IsPendingKill pretty much any time you want to access them. It’s not strictly a dangling pointer, but from a behaviour point of view it’s still dangerous not to check.

So essentially, just saying I think this is a very valid question, and the lack of support for TWeakObjectPtrin blueprints is a pain!

TSoftObjectPtr is supported by Blueprints:

UPROPERTY(Category = Default, EditAnywhere, BlueprintReadWrite)
	TSoftObjectPtr<AActor> SomePtr; //SomePtr.Get();

Interesting. Technically that’s meant for objects with a persistent path (assets, or placed actors in a map file) that can be reloaded if they drop out of memory. Since that doesn’t apply to dynamically spawned actors, it feels a little hacky, but if blueprint lets you do it then I’d probably prefer it to a raw pointer.

Given that TSoftObjectPtr is implemented as a weak pointer + asset path, it kind of confirms that there’s no good reason why Blueprint shouldn’t support regular weak object pointers.