Hi Klaus,
TArray works fine. The problem is with the life time of your UObjects, such as UStaffUnit, UStaffMember, etc.
What you need to know is that UObjects in UE4 are special in that they are garbage collected objects. The engineâs garbage collector will regularly sweep all UObjects in memory and determine whether or not anything still references those objects. If nothing references an object, the garbage collector will destroy it. This system frees you from the burden of managing the life time of your game objects yourself, which could get really quite complicated for any non-trivial game logic.
Now, with great power also comes great responsibility. In particular, it is your responsibility to tell the garbage collector when a UObject is still being referenced. In UE4 we handle this via so called UProperties. Those are class member fields in your class declaration that are marked up with the UPROPERTY() macro. This macro will be detected by Unreal Header Tool (UHT) when you compile your code, and cause it to generate the hidden magic glue that is needed by the garbage collector to become aware of the fact that your object is referencing some other UObject. Note that in C# and Java this all happens automatically, because it is a feature built into the language. C++ does not have these capabilities out of the box, which is why we need to use these kind of tricks instead.
So, basically, what you are missing is the UPROPERTY() markup in all the places where you keep pointers to UObjects. For example, in UStaffManager, the following would be the correct code:
[FONT=Courier New]UPROPERTY()
UStaffGenerator* Generator; // Factory class for creating UStaffMNember instances
UPROPERTY()
UStaffUnitList* StaffUnits; // Array with all UStaffUnit instances
UPROPERTY()
UExitUnit* ExitUnit; // Special Exit unit ith extended behaviour
UPROPERTY()
UStaffUnit* AllStaff; // Array with a duplicate pointer to each UStaffMember instance referenced by âŚ
With these changes, the garbage collector will be able to discover that UStaffManager may hold references to UStaffGenerator, UStaffUnit, and other UObject derived instances. You have to do this whenever you wish to hold on to UObject instances beyond the scope of the current function call. In local function calls it is OK to simply reference a pointer to a UObject derived class.
If you donât mark up your pointers with UPROPERTY, what happens is that the garbage collector thinks that nothing in your game is still referencing your newly created instances of UStaffUnit etc. It then correctly frees the memory of those objects. This can happen a short time after you created them. Once the object is freed, the memory associated with it becomes invalid and may be reused by other objects. This is why your TArray ends up having ârandomâ data in it, and why youâre seeing an odd array size of -572662307. The memory of the TArray is basically all garbage.
Bonus knowledge: If you need to hold on to a UObject within a non-UObject class (i.e. a regular C++ class), then you cannot use the UPROPERTY() markup. Instead you use the TWeakObjectPtr template to store your pointers. Note that this is a weak pointer, meaning that it does not take ownership of the life time of your object. However, this pointer will be automatically reset to nullptr once the garbage collector destroys the referenced UObject. Before dereferencing a weak object pointer you must therefore check whether it is actually still valid.
I hope this clears everything up.
In general, the rule of thumb is this: If you seemingly run into an issue with basic core types in UE4 then the problem is your code, not UE4. The core types have evolved over 25 years and stood the test of time. While it is not impossible, it is extremely unlikely that they are broken. Also, if they were broken, we would detect it pretty much immediately, because they are used in innumerable ways in the Engine.
Here are some useful documentation links:
Garbage Collection Overview
Unreal Object Handling
UNREAL PROPERTY SYSTEM (REFLECTION)
Properties
UPROPERTY