jesse-dino
Topic Author
Posts: 7
Joined: 23 Apr 2025, 20:43

Unreal TArray update best practices

13 Jun 2025, 18:57

I'm looking for recommendations on best practices for updating TArrays.
The various NoesisNotifyArrayProperty___ functions are clear enough when you only have a single action to perform, but when you have multiple updates to make it becomes less clear. Are there significant performance benefits or penalties between the various APIs?

tl;dr - What are the cleanest code & optimal performance ways to update a list in tandem with TArray::SetNum?

A common pattern is to be given a new updated list and have to update the currently bound list to match (e.g. a new Model from a server API, and resizing and element-by-element updating a ViewModel). Typically we'd resize the ViewModel array (TArray::SetNum) then iterate through the list, but honestly the code for this seems really messy, and we're prevented from optimizing the shrinking case - thereby potentially hitting multiple resize events.

- If we're growing the array, call PreAppend, then resize
- If we're shrinking the array, don't resize
- Iterate through every element in the new array, and if it was an element in the old list call NotifySet, and if it's a brand new element don't call set
- If we grew the array, call PostAppend (is it ok to interleave this with the set calls?)
- If we're shrinking the array, iterate backwards, and if it's an element to delete call NotifyPreRemove, then remove the element, then NotifyPostRemove, one element at a time.

We could make this SLIGHTLY cleaner by calling PostAppend immediately after the resize, and then calling Set on those elements after we update them - but I imagine this has a perf impact for essentially double-notifying on each added element?
We could also make it slightly cleaner by not using the Append functions, and instead individually either `NotifyPostInsert` or `Remove` each grown/shrunk element. Does this have any performance impact?
What about using SetNum for both growing and shrinking the array, and then just multiple calls of Notify(Pre/Post)(Insert/RemoveAt) after the fact (in other words, do the Pre calls really have to happen before we remove the item from the ViewModel - it feels unsafe, but is it?)

Example code here for what I think is required: https://gist.github.com/JesseOlmer/2bee ... 593a69fe4b
 
User avatar
hcpizzi
Site Admin
Posts: 368
Joined: 09 Feb 2012, 12:40

Re: Unreal TArray update best practices

17 Jun 2025, 19:55

Hi Jesse,

As a rule of thumb, the more specific the notifications, the better. I've tested both the case where the array grows as well as the one where it shrinks. The first bit is the same in both cases: use NotifyPre/PostSet to move elements that remain on the array to the front.

Then, if there are more elements remaining, you can do NotifyPreAppend, then update the array, then NotifyPostAppend.

If, to the contrary, there's leftover space at the end of the array, you can call NotifyPreRemove and NotifyPostRemove in a loop, then remove the tail of the array, or you can do NotifyPreRemove, remove the element, NotifyPostRemove.

As for the final questions, the PostAppend is basically a loop of PostInserts and PreInsert just keeps the old item count to know how many Inserts to notify. There's no equivalent for the remove functions because the notification needs the old value, so PreRemove fetches the value, PostRemove sends the notification. So yes, the Pre calls need to happen before the array is modified, because they need the state of the array before the modifications.

One final thing: Natively there's also a Move notification that is not exposed in Unreal, but we could add it. That should help with the initial sorting of the items that remain.
 
jesse-dino
Topic Author
Posts: 7
Joined: 23 Apr 2025, 20:43

Re: Unreal TArray update best practices

18 Jun 2025, 00:19

Thanks, that all makes sense and is what I landed on in my testing as well. Being able to tell Unreal to defer shrinking on removes helped as well.

A related problem: UObjects are pretty heavy weight, and in a lot of cases USTRUCTs are preferable, especially when managing lists of items. All of the NoesisNotify functions only appear to work with UObjects. The naive approach to changing an array of USTRUCTs (just calling NoesisNotifyArrayPropertySet) can get expensive quickly, especially once nested types are involved. Even 1 layer of nesting and < 30 objects can easily result in >5ms frame time depending on the control templates.

Is there a syntax trick we can use to still be able to work with USTRUCTS in this case but allow more fine-grained updates? Maybe something akin to
NoesisNotifyPropertyChanged(ParentUObject, TEXT("Children[1].ChildUProperty"))
?
Ideally we'd be able to NotifyPropertyChanged directly on a UStruct pointer, but I don't see that in the API anywhere.
 
User avatar
hcpizzi
Site Admin
Posts: 368
Joined: 09 Feb 2012, 12:40

Re: Unreal TArray update best practices

18 Jun 2025, 17:55

I'm afraid that, unfortunately, structs are treated as having value semantics, so individual fields within them cannot be notified, only the whole structs within its container (UObject or collection).

Who is online

Users browsing this forum: No registered users and 2 guests