Skip to content

Vector Length / Vector Length XY / Normalize

At a glance

Lives in: Kismet Math Library; Blueprint API / Math / Vector - Returns: Vector Length and Vector Length XY return a real number; Normalize returns a Vector - none can return None - Fails by: Normalize returns (0, 0, 0) when the input is too small for its squared-length tolerance; the length nodes return 0 for a zero vector - Official docs: Vector Length, Vector Length XY, and Normalize

The one-minute version

  • A vector contains an amount on three axes. Length turns that vector into one non-negative scalar: its magnitude.
  • Vector Length uses X, Y, and Z. Vector Length XY ignores Z.
  • Get Velocity -> Vector Length XY is the usual ground-speed calculation. Use full length for flight, swimming, projectiles, or any other genuinely 3D motion.
  • Normalize keeps the direction but changes a safely large vector to length 1. It removes the original distance or speed.
  • A zero or near-zero vector has no dependable direction. Normalize returns (0, 0, 0) when the input's squared length is below its tolerance.
  • To find direction from A to B, subtract first, then normalize: Normalize(B - A).
  • Use a squared-length node for threshold comparisons when you do not need the actual distance. Compare it with the threshold squared.
  • Normalizing a raw analog-stick vector makes almost every nonzero input full strength. Preserve or clamp analog magnitude when partial input matters.

What each node returns

For A = (X, Y, Z), the operations have these shapes:

Vector Length(A)    = sqrt(X*X + Y*Y + Z*Z)
Vector Length XY(A) = sqrt(X*X + Y*Y)
Normalize(A)        = A / Vector Length(A), when A is safely large

Examples:

Input Vector Length Vector Length XY Normalize
(3, 4, 0) 5 5 (0.6, 0.8, 0)
(0, 0, -600) 600 0 (0, 0, -1)
(0, 0, 0) 0 0 (0, 0, 0)

Length is always non-negative. It does not tell you which way the vector points. A velocity of (600, 0, 0) and one of (-600, 0, 0) both have length 600.

Normalize returns another vector. A successful result has length approximately 1, so it represents direction without the original magnitude:

Original vector = Direction * Magnitude
Direction       = Normalize(Original vector)
Magnitude       = Vector Length(Original vector)

These are pure calculations. They do not move an Actor, change the input vector, cache a result, or add an execution pin.

Units follow the input

The length nodes do not invent units. Their result uses the same base unit as the vector's components:

Vector means Components use Length means
Target Location - Start Location centimeters distance in centimeters
Get Velocity centimeters per second speed in centimeters per second
normalized direction no unit approximately 1
arbitrary RGB-style data arbitrary values mathematical magnitude, not world distance

In normal Unreal world-scale projects, one Unreal unit is one centimeter. That does not make every vector a location: velocity, direction, scale-like data, and world position can all use the same Vector pin type.

Length or Length XY?

Choose based on the movement plane, not on which number looks better.

Get Velocity
-> Vector Length XY
-> GroundSpeed

This ignores jump and fall velocity. A Character falling straight down can have a large 3D speed while its ground speed remains zero. That is usually what a walking Blend Space needs.

Use full Vector Length when vertical motion belongs in the answer:

  • flight and swimming;
  • homing projectiles;
  • free-flying cameras;
  • distance between two arbitrary 3D points;
  • impact or physics velocity magnitude.

Ignoring Z is a design choice, not a general performance trick. On steep slopes, XY speed is the horizontal projection rather than total speed along the slope.

See Get Velocity for where Actor velocity comes from and why direct transform changes can still report zero.

Normalize and the near-zero case

A zero vector cannot be divided by its length because that length is zero. Very tiny vectors are also poor directions: dividing by a tiny number can turn floating-point noise into a seemingly decisive unit vector.

Normalize therefore uses a safety check:

pseudocode - not engine source

if SquaredLength(A) is large enough for Tolerance:
    return A / sqrt(SquaredLength(A))
else:
    return (0, 0, 0)

The node's Tolerance is a minimum squared vector length, not an ordinary distance. The default is appropriate for ordinary gameplay math. Change it only when the scale and meaning of your data justify a different cutoff.

The fallback is silent. There is no None, failure Boolean, warning, or exception. If zero direction means "no target direction" in your graph, test for that state before acting:

ToTarget = TargetLocation - SourceLocation

if Vector Length Squared(ToTarget) > MinimumDistance * MinimumDistance:
    Direction = Normalize(ToTarget)
    use Direction
else:
    treat source and target as being at the same point

Do not lower tolerance just to force an answer from two almost identical positions. Decide what "close enough" means for the gameplay system.

The patterns everyone actually uses

Distance from one point to another

Offset   = TargetLocation - StartLocation
Distance = Vector Length(Offset)

The length of either world location by itself is its distance from world origin, which is rarely the intended question.

Direction and distance together

Offset    = TargetLocation - StartLocation
Distance  = Vector Length(Offset)
Direction = Normalize(Offset)

Keep both values when arrival logic needs distance while movement or aiming needs direction.

Ground speed for animation

OwnerCharacter
-> Get Velocity
-> Vector Length XY
-> set GroundSpeed

This is actual movement speed, not input intent. A blocked Character may have movement input while velocity remains near zero.

A displacement for this frame

FrameDisplacement = Direction * Speed * DeltaSeconds

Direction should be unit length, Speed is distance per second, and DeltaSeconds converts that rate into a per-frame distance. Normalize does not make manual movement frame-rate independent by itself; see The frame.

Diagonals and movement input

Combining full-strength forward and right values produces (1, 1, 0), whose length is about 1.414. A custom system that multiplies this vector directly by speed can move diagonally about 41 percent faster.

For digital input, combine first and then limit the result:

Desired = Forward * ForwardAxis + Right * RightAxis

if Vector Length Squared(Desired) > 1:
    Desired = Normalize(Desired)

Some movement systems already constrain accumulated input, but custom movement code should make its own magnitude rule explicit. See Add Movement Input for the Pawn and Character input path.

For an analog stick, unconditional normalization is usually wrong:

Stick = (AxisX, AxisY, 0)
Normalize(Stick)  // turns a small tilt into almost full strength

Instead, preserve values inside the unit circle and clamp only values above length 1. Apply a dead zone before movement if the device needs one. Tier 36's Enhanced Input modifier page covers that input-specific path.

Is it okay to normalize every frame?

Yes, when a direction is genuinely changing each frame. These nodes are small, side-effect-free math operations. Correctness is usually more important than trying to avoid one square root.

Still, normalize at the point where the value becomes a direction:

  • do not repeatedly normalize a known unit vector such as Get Forward Vector;
  • do not normalize and then expect to recover the old speed;
  • do not normalize each axis separately before combining them;
  • do not normalize analog input when its magnitude is intentional;
  • do normalize changing offsets, surface directions, or custom movement directions before code assumes unit length.

Squared length for comparisons

Vector Length Squared and its 2D/XY counterpart skip the square root. Use them when the only question is whether one distance is above or below a threshold:

Offset = TargetLocation - StartLocation

Vector Length Squared(Offset) <= AttackRange * AttackRange

Both sides must be squared. Comparing squared length directly with AttackRange mixes different units and gives the wrong boundary. Do not show squared length to a player as if it were a distance, and do not use it as a speed value for animation.

The C++ twins

For the curious, the same operations in original example code are:

const FVector Velocity = ControlledActor->GetVelocity();
const double Speed3D = Velocity.Size();
const double GroundSpeed = Velocity.Size2D();

const FVector Offset = TargetLocation - ControlledActor->GetActorLocation();
const double DistanceSquared = Offset.SizeSquared();

if (DistanceSquared <= FMath::Square(AcceptanceRadius))
{
    return;
}

const FVector Direction = Offset.GetSafeNormal();

Size, Size2D, SizeSquared, and GetSafeNormal are FVector operations. Use the engine's safe-normal helper rather than dividing by length manually.

Lookalikes - which one do I want?

Node Returns Use when Watch out
Vector Length Real You need full 3D distance or speed. Includes Z.
Vector Length XY Real You need horizontal/ground magnitude. Discards vertical motion.
Vector Length Squared Real You only need a threshold comparison. Compare with a squared threshold.
Normalize Vector You need direction without magnitude. Near-zero input returns zero.
Get Forward Vector Unit Vector You need the X-forward direction of a rotation/component. It is already a direction, not a location.
Get Unit Direction Vector Unit Vector You want the direction from one point to another. Coincident points still produce zero.
Distance (Vector) Real You want distance between two points directly. It is the length of their difference.
Clamp Vector Size Vector You need to limit magnitude without forcing small values to length 1. Choose 2D vs 3D deliberately.

Going deeper

  • Get Forward Vector & Find Look at Rotation - direction sources, world-space points, and aim rotations.
  • Get Velocity - actor velocity, ground speed, and zero-velocity cases.
  • Blend Spaces in Animation Blueprints - using ground speed as animation data.
  • Lerp, FInterp To, and moving things smoothly - interpolation is not normalization.
  • Official docs: Vector Length, Vector Length XY, and Normalize.
  • Engine source (requires engine access - we do not reproduce it here): Kismet wrappers such as UKismetMathLibrary::VSize, UKismetMathLibrary::VSizeXY, and UKismetMathLibrary::Normal are declared in Engine/Source/Runtime/Engine/Classes/Kismet/KismetMathLibrary.h and implemented in Engine/Source/Runtime/Engine/Private/KismetMathLibrary.cpp; vector math such as TVector::Size, TVector::Size2D, and TVector::GetSafeNormal lives in Engine/Source/Runtime/Core/Public/Math/Vector.h.