Skip to content

Set Array Elem / Resize / Clear / Append Array

At a glance

Lives in: Kismet Array Library; Blueprint API / Utilities / Array - Mutates: the connected Target Array - Returns: no data value and no success Boolean - Shape changes: Set Array Elem only when Size to Fit grows; Resize sets an exact Length; Clear sets Length to zero; Append adds the Source Array's elements at the end - Invalid input: normally leaves the array unchanged, continues execution, and writes an array warning in editor/development output - Official docs: Set Array Elem, Resize, Append Array, and Kismet Array Library

The one-minute version

  • Set Array Elem replaces the value at one zero-based index. It does not insert or shift later items.
  • With Size to Fit = false, the index must already be valid (0 through Length - 1). An invalid/negative index produces no success pin; the array stays unchanged and a development/editor array warning is the visible clue.
  • With Size to Fit = true, a non-negative index beyond the end grows the array to Index + 1. Every skipped slot receives the element type's default value before the requested slot is assigned.
  • Resize preserves the prefix that still fits, default-fills a grown tail, or removes a shrunken tail. Clear guarantees Length == 0.
  • Append Array copies the source elements, in order, onto the target's end. Values/structs are copied; object-reference elements still point to the same runtime objects. It allows duplicates and returns no count or success value.
  • None of these nodes replicate, save, destroy referenced Actors/UObjects, or tell a ListView/inventory UI that the model changed. Those are separate owner-system jobs.

Start with the shape, not the node name

Given:

Items = [Potion, Key]
index      0      1
Length = 2

the nodes make different promises:

Operation Result
Set Array Elem(Index 1, Map) [Potion, Map]; Length stays 2.
Set Array Elem(Index 2, Map, Size to Fit false) Warning; unchanged because index 2 does not yet exist.
Set Array Elem(Index 2, Map, Size to Fit true) [Potion, Key, Map]; Length becomes 3.
Set Array Elem(Index 4, Map, Size to Fit true) [Potion, Key, default, default, Map]; Length becomes 5.
Resize(4) [Potion, Key, default, default].
Resize(1) [Potion]; the old Key slot is removed.
Clear []; Length becomes 0.
Append Array([Map, Key]) [Potion, Key, Map, Key]; duplicates are kept.

No operation above sorts, de-duplicates, or shifts an existing item to make room at a chosen index. Choose the shape change deliberately.

What Set Array Elem actually does

Set Array Elem is assignment into a slot:

pseudocode of the Blueprint behavior - not engine source

function SetArrayElem(Array, Index, Item, SizeToFit):
    if Index < 0:
        emit array warning
        return

    if Index >= Length(Array):
        if not SizeToFit:
            emit array warning
            return

        Resize(Array, Index + 1) // new slots receive defaults

    Array[Index] = copy of Item

The node has an execution output but no result output. Execution continuing only means the node call finished; it does not prove the write happened.

Replacing does not insert

Starting from [A, B, C]:

Set Array Elem(Index 1, X) -> [A, X, C]
Insert(Index 1, X)         -> [A, X, B, C]

Use Set when the slot identity should stay put. Use Insert when every existing item at/after the position should shift right.

What Size to Fit means

Size to Fit does not find an empty slot. It does not add only one item. It makes the requested index legal by growing Length to exactly Index + 1.

Current Length = 2
Set index 100 with Size to Fit = true
-> Length becomes 101
-> slots 2..99 are default values
-> slot 100 receives Item

That can be intentional for a dense array keyed by a small, bounded slot number. It is usually a data-model bug when the index is a sparse database ID, network ID, or unchecked user value. A Map expresses sparse key-to-value data without allocating every missing integer position.

Negative indices can never be made valid. Size to Fit does not turn -1 into the last slot.

Which defaults fill a grown gap?

Growth initializes each new slot to the element type's default:

Array element type Typical new-slot value
Integer / Real 0 / 0.0
Boolean false
String / Text / Name empty/default value
Object or Actor reference None
Class reference None unless the type/property supplies another default
Vector / Rotator / Transform-like value its type default (commonly zero/identity as defined by that type)
Struct a default-initialized struct, including member defaults supplied by the type

Do not treat a default-filled slot as proof that real data exists there. An Object Array grown to index 8 now has valid indices 0..8, but the gap slots can contain None. Is Valid Index and Is Valid answer different questions.

Struct copy write-back: the Set pattern beginners need

The normal Array Get for a struct gives you a value copy. Changing that copy does not mutate the struct still stored in the array:

wrong:
    Entry = Get Inventory[Index]
    Entry.Count = Entry.Count + 1
    // Inventory still contains the old struct

right:
    Entry = Get Inventory[Index]
    Entry.Count = Entry.Count + 1
    Set Array Elem
        Target Array = Inventory
        Index = Index
        Item = Entry
        Size to Fit = false

Validate the index before Get and again if any called event/function could mutate the array before Set. The local Entry is a snapshot; another mutation can make its saved index point at a different intent or no slot at all.

For an object-reference element, Array Get copies the reference value. Both copies point at the same object, so changing that object's properties changes the live object. Replacing the array slot changes which reference the array stores; it does not clone or destroy either object.

Resize: set the exact Length

Resize takes the final desired element count, not an amount to add or remove:

Items = [A, B, C]

Resize(5) -> [A, B, C, default, default]
Resize(2) -> [A, B]
Resize(0) -> []

The prefix 0..min(old Length, new Length)-1 keeps its values and order. Growing creates defaults at the tail. Shrinking removes the tail; it does not choose items by equality and does not move the removed values elsewhere.

A negative Size is invalid. The node has no failure output; the useful array stays unchanged and the engine reports an array warning in development/editor output. Clamp or reject an externally calculated size before calling Resize.

What becomes stale after Resize?

  • Saved indices: indices below the new Length still identify the same positions because Resize does not reorder the retained prefix. Every removed index is invalid.
  • Struct/value copies already read: they remain old snapshots. They do not follow later writes to the array.
  • Object references already read: they still identify the same object if that object remains valid; they are no longer proof that the array contains it.
  • Element references/native addresses: growth can reallocate the dynamic array, and shape mutations can invalidate references into its storage. Do not retain an element-by-reference path across Resize, Clear, or Append.

Removing an object-reference slot only removes this array's reference. It does not call Destroy Actor. A UObject with no remaining strong references may later become eligible for garbage collection; an Actor follows its own world lifetime and destruction rules.

Clear: Length becomes zero

Clear removes every logical element:

Clear(Items)
-> Length = 0
-> Last Index = -1
-> no element can be read

That is the guarantee Blueprint code should use. Blueprint exposes no Array capacity contract, so do not treat Clear as a promise that backing allocation was retained for pooling or immediately returned to the operating system. Capacity is an implementation/performance detail; logical contents are not.

Clear also does not destroy referenced objects. It releases this collection's references, after which ordinary Actor/UObject lifetime rules decide what happens.

Use Clear when the same Array variable should become empty. Assigning a new empty Array can express the same logical result, but Clear makes the in-place mutation visible in the graph and works naturally with an Array passed by reference.

Append Array: concatenate a source onto a target

Append copies the Source Array's current elements, in order, onto the Target Array's tail:

Target = [A, B]
Source = [C, D]

Append Array(Target, Source)
-> Target = [A, B, C, D]
-> Source = [C, D]

The source's Length is added to the target's Length. An empty source is a successful no-op: target remains unchanged and there is no special branch.

Append does not test equality. If Target already has C, appending [C] creates another C. Use Add Unique/Set/Map only when uniqueness is the actual collection contract.

Copying values versus sharing objects

For Integer, Vector, and struct arrays, the appended elements are value copies. Changing a struct in Source later does not rewrite the struct copy in Target.

For object-reference arrays, the reference values are copied:

Source[0] -> Enemy_12
Target appended slot -> Enemy_12

Both arrays now point at the same Enemy_12 object. Changing the object is visible through either reference; replacing/removing one array slot does not rewrite the other array.

Do not alias Target and Source

Epic's Blueprint page documents appending a source array to a target, but does not promise a result when both pins alias the same Array storage. The native TArray self-append contract is unsupported. Do not rely on an observed engine version doubling the array, warning, or doing nothing.

Make the snapshot explicit when duplication is intended:

Copy = Items              // Array value copy
Append Array
    Target Array = Items
    Source Array = Copy

Now the source is stable even if growing Target reallocates its storage. This is the structurally safe pattern across engine versions.

When an operation does nothing or warns

These nodes do not throw exceptions and do not run a hidden failure branch.

Situation Visible result Array result
Set receives a negative Index Array warning in editor/development output; execution continues unchanged
Set receives Index >= Length, Size to Fit false Array warning; execution continues unchanged
Set receives a non-negative out-of-range Index, Size to Fit true no bounds failure if the requested size is supported grows to Index + 1, then writes
Resize receives a negative Size Array warning; execution continues unchanged
Clear receives an already-empty Array no special result remains empty
Append receives an empty Source no special result unchanged
Growth would exceed the engine's supported container size development warning/no success pin no reliable requested mutation; validate bounds yourself

If gameplay must know that a write occurred, validate before the call and/or read the resulting Length/value afterward. The execution wire itself is not a success signal.

The patterns everyone actually uses

Initialize a fixed slot array once

BeginPlay:
    Resize(HotbarSlots, 8)

AssignHotbarSlot(Index, Item):
    Branch Is Valid Index(HotbarSlots, Index)
    true:
        Set Array Elem(Index, Item, Size to Fit = false)

One owned initialization step establishes the invariant. Later writes do not silently grow the hotbar because of a bad input index.

Grow only to a bounded requested slot

SetUnlockedReward(RewardIndex, Reward):
    require RewardIndex >= 0 AND RewardIndex < MaxRewardSlots
    Set Array Elem
        Index = RewardIndex
        Item = Reward
        Size to Fit = true

The explicit upper bound prevents a corrupted ID from allocating a giant default-filled gap.

Rebuild a derived list, then notify once

RebuildVisibleItems:
    Clear(VisibleItems)
    Append Array(VisibleItems, EquippedItems)
    Append Array(VisibleItems, BackpackItems)
    Broadcast OnVisibleItemsChanged

The Array nodes only create the model shape. The final event tells presentation that one coherent rebuild is complete.

Mutate an inventory struct and write it back

if Inventory Is Valid Index(Index):
    Entry = Inventory[Index]
    Entry.Count = Entry.Count + AddedCount
    Set Array Elem(Inventory, Index, Entry, Size to Fit = false)
    Broadcast OnInventoryChanged

The inventory's replication, SaveGame copy, weight totals, and UI refresh stay with the system that owns Inventory rather than being implied by Set Array Elem.

Replication, SaveGame, and UI are separate

These Array operations mutate one in-memory variable on the machine running the graph.

  • Replication: mutate authoritative gameplay arrays on the server. A replicated property can send its later state through the replication system, but the Array node itself is not an RPC and a client mutation does not upload authority.
  • SaveGame: changing a runtime Array does not write a slot. Copy/serialize the intended data into a SaveGame object and call the save workflow.
  • User interface: a Widget binding, ListView, or cached entry widget may not know the model changed. Broadcast one owner event and refresh/reconcile the view through its documented path.

Keep mutation plus notification in one owner function. Scattering direct Set/ Clear calls across actors makes it impossible to guarantee that derived totals, replication rules, and UI updates stay paired.

What these nodes do not do

They do not:

  • validate gameplay meaning just because an index is numerically valid;
  • use -1 as the last element;
  • insert or shift items when Set replaces a slot;
  • de-duplicate, sort, or compact default gaps;
  • update struct copies that were read earlier;
  • clone objects when object references are appended;
  • destroy an Actor/UObject when its reference is removed;
  • guarantee a Blueprint-observable memory-capacity policy;
  • replicate or save the mutation; or
  • broadcast an inventory/ListView/model-changed event.

Lookalikes - which one do I want?

Node Use when Shape/return difference
Set Array Elem Replace one known slot; optionally grow to that index. No shift and no success output.
Resize Establish an exact Length. Preserves a fitting prefix; default-fills or removes the tail.
Clear The same Array should become empty. Length becomes zero; referenced objects are not destroyed.
Append Array Copy a whole source sequence onto the end. Duplicates allowed; source unchanged; no count output.
Add Append one item. Returns the new index.
Add Unique Append one item only when no equal value exists. Equality scan; Blueprint returns -1 if already present.
Insert Put one item before an index and shift the tail. Length grows by one; later indices move.
Remove Index / Item Delete one position or all equal values. Later indices can shift left.
Set Array variable Replace the entire Array value from another Array. Expresses whole-value assignment rather than in-place concatenation.
Map Sparse/stable keys retrieve values. No giant default-filled integer gap; keys are not array positions.

Rule of thumb: Set replaces a slot, Resize owns Length, Clear owns empty, Append copies a sequence, and Map owns sparse keys.

C++ twins

Original example code:

if (Items.IsValidIndex(Index))
{
    Items[Index] = UpdatedItem;
}

Items.SetNum(DesiredLength);     // grow with defaults or remove the tail
Items.Reset();                   // logical empty; capacity policy is explicit in C++
Items.Append(MoreItems);         // MoreItems must not alias Items

C++ has direct access to capacity/reserve choices and can use return values or assertions around project invariants. Blueprint's four nodes intentionally present the simpler reflected-container contract.

Going deeper

  • Array Get / Length / Last Index / Is Valid Index - safe reads, empty arrays, copy/reference behavior, and index guards.
  • Array Add / Add Unique / Insert / Remove / Find / Contains - one-item mutation, equality, return values, and shifting indices.
  • Arrays, Sets, Maps, and ForEach - choose the collection shape before choosing a node.
  • Add, Remove, Stack, and Broadcast Inventory Changes - the model-owner contract around primitive Array writes.
  • Blueprint variables and references - value copies versus references to live UObjects.
  • Is Valid - object lifetime after an index has already been proven valid.
  • Replication basics - why a local container mutation and authoritative replicated state are different.
  • Official docs: Resize, Append Array, Array Containers, and TArray.
  • Engine source (requires engine access - we do not reproduce it here): UKismetArrayLibrary::GenericArray_Set, UKismetArrayLibrary::GenericArray_Resize, UKismetArrayLibrary::GenericArray_Clear, and UKismetArrayLibrary::GenericArray_Append in Engine/Source/Runtime/Engine/Private/KismetArrayLibrary.cpp; Blueprint declarations and maximum-container warnings in Engine/Source/Runtime/Engine/Classes/Kismet/KismetArrayLibrary.h; generic reflected element initialization/copying in FScriptArrayHelper under Engine/Source/Runtime/CoreUObject/Public/UObject/UnrealType.h; and native TArray::SetNum, TArray::Reset, and TArray::Append in Engine/Source/Runtime/Core/Public/Containers/Array.h.