Plugin Documentation

MorphCue
Morph targets played straight from your animation tracks

Drop a Morph Cue notify on any animation sequence or montage, pick morph targets from the preview mesh and they play in sync with the animation: blinks, smiles, muscle bulges, corrective shapes, cloth wrinkles. Layer several morphs, ease them, loop them, blend them over the current shape, play whole presets, drive modular characters and mirror left/right names. A Morph Cue Player component plays the same thing from Blueprint or C++ without any animation.

v1.0
UE 4.27 & 5.8
Win64 & Mac
Category Animation
C++ & Blueprint
Alpha XP

Overview

Morph targets (also called blend shapes or shape keys) are usually driven by curves baked into the animation or by gameplay code. MorphCue lets animators drive them right on the notify track of the animation editor, with no code and no curve authoring, and lets programmers drive the same morphs from Blueprint or C++.

  • Morph Cue notify state: place it on a sequence, montage or composite; its length is the playback length.
  • Layered morphs: one notify drives any number of morph targets, each with its own values and timing.
  • Easing library: Linear, Sine, Quad, Cubic, Expo, Smooth Step, or your own Curve Float.
  • Loops and windows: repeat a layer N times and play it over only part of the notify.
  • Blend modes: Override, Additive or Multiply against the weight the morph had when the cue began.
  • End actions: keep the final value, restore the previous value or reset to zero - also when the animation is interrupted.
  • Morph presets: data assets of named weights (expressions, visemes, body shapes) played by a notify, the component or the library.
  • Modular characters: also drive attached skeletal meshes or every mesh on the actor, filtered by component tag.
  • Random variation: random end value and random delay on every play, so repeated blinks never look identical.
  • Mirroring: swap _L/_R (or any token pair) in morph names for mirrored animations.
  • Morph Cue Player component: play, blend, preset and stop morphs at runtime with a finished event.
  • Searchable morph picker in the details panel, filled from the preview mesh, with free typing and unknown-name highlighting.
  • Safe on many characters at once: every mesh running the same animation keeps its own cue state.

Requirements

RequirementDetails
Unreal Engine4.27 and 5.8
ModulesMorphCue (Runtime) and MorphCueEditor (Editor, details panel picker only)
DependenciesNone (engine modules only; no other plugins are enabled)
MeshAny skeletal mesh imported with morph targets
PlatformsWin64 and Mac (the modules list these platforms in the plugin descriptor). The code is platform-independent engine C++ with no OS-specific calls.
Network ReplicatedNo. Morph targets are cosmetic: notifies run on every machine that plays the animation.

Installation

  1. Install MorphCue from Fab into your engine, or copy the MorphCue folder into your project's Plugins folder.
  2. Enable MorphCue in Edit > Plugins and restart the editor.
  3. C++ only: add PublicDependencyModuleNames.Add("MorphCue"); to your Build.cs.
Verifying the installRight-click a notify track in any animation: Add Notify State > Morph Cue is listed.

Quick start

  1. Open an animation sequence or montage of a mesh that has morph targets.
  2. Right-click a notify track and choose Add Notify State > Morph Cue. Drag its ends to the frames where the morph should play.
  3. Select the notify. In Layers, expand element 0 and click Pick next to Morph, then choose a morph target.
  4. Keep Playback on A to B to A, set End (B) to 1 and scrub or play: the morph rises and falls over the notify.
  5. Add more layers for more morphs, or set a Preset to play a whole expression.
TipThe notify's name on the track shows what it plays, for example Morph Cue: EyeBlink_L +1 (Mirrored).

The Morph Cue notify

Notify State UMorphCueNotifyState — displayed as Morph Cue.

PropertyDefaultDescription
Layers1 empty layerMorph targets played by this cue (see Layers).
PresetNoneOptional preset: each of its morphs plays from 0 to its preset weight.
Preset Weight1Scale applied to the preset weights.
Preset Playback / Preset EasingA to B to A / Sine In OutHow the preset morphs are played.
End ActionKeep Final ValueWhat happens to the morphs when the notify ends or the animation is interrupted.
Time SourceElapsed TimeElapsed Time accumulates frame time. Animation Time reads the animation's own time, so it follows play rate and editor scrubbing (UE 5.8; UE 4.27 uses elapsed time).
Mesh Targets / Mesh TagThis Mesh / NoneWhich meshes are driven (see Modular characters).
Mirror / Mirror PairsOff / _L-_R, _l-_r, Left-RightSwap left/right tokens in every morph name (see Mirroring).

Blueprint children of the notify can implement event On Cue Begin (mesh, total duration) and event On Cue End (mesh). pure Get Resolved Layers returns the layers that will play (preset expanded, names mirrored) and Get Active Instance Count the number of meshes running the cue.

One notify, many charactersA notify object is shared by every mesh that plays its animation. MorphCue keeps a separate state for each mesh and animation, so a crowd playing the same clip at different times is driven correctly, and the state of destroyed meshes is dropped automatically.

Layers

struct FMorphCueLayer — one morph target over a window of the cue.

FieldDefaultDescription
MorphNoneThe morph target (picker, see Morph picker).
PlaybackA to B to AA holds the start value, A to B, B to A, A to B to A.
Start (A) / End (B)0 / 1The two weights. Values outside 0-1 are allowed (over-driven or negative shapes) and B may be lower than A.
Easing / Custom CurveLinear / NoneEasing of each playback segment; Custom Curve maps time 0-1 to alpha (0 = A, 1 = B).
Blend ModeOverrideSee Blend modes.
Loops1How many times the playback repeats inside the window.
Window Start / Window End0 / 1Part of the notify the layer plays over, as fractions of its length. Before the window the layer holds its first value, after it the final value.
Random End Offset0Each play adds a random offset in [-X, X] to B.
Random Delay0Each play starts the layer later by a random fraction of its window, up to X (max 0.9).
Example: a natural blinkLayer EyeBlink_L, A to B to A, Sine In Out, Window 0-0.4, Random Delay 0.2, Random End Offset 0.05; turn on Mirror and add a second notify for the right eye, or add a second layer EyeBlink_R.

Playback, easing & loops

At each frame a layer computes its progress through its window (0 to 1), splits it into Loops cycles and turns each cycle into a shape between A (0) and B (1):

PlaybackShape over one cycleFinal value
Aconstant AA
A to Bease(t)B
B to A1 - ease(t)A
A to B to Aease(2t) for the first half, ease(2 - 2t) for the secondA

Easings: Linear, Sine In, Sine Out, Sine In Out, Quad In, Quad Out, Quad In Out, Cubic In Out, Expo In Out, Smooth Step and Custom Curve. When the notify ends, the layer is snapped to its exact final value (with Keep Final Value) even if the last frame stopped short of it.

Blend modes & end actions

When a cue begins, MorphCue reads the current weight of each of its morphs on each target mesh (the starting weight).

Blend ModeWeight writtenUse it for
Overrideplayed valueMost cues.
Additivestarting weight + played valueA bulge or wrinkle on top of a shape set by gameplay.
Multiplystarting weight × played valueTemporarily damping a shape (B = 0 fades it out).
End ActionResult when the notify ends
Keep Final ValueThe final value of the playback stays on the mesh.
Restore Previous ValueEach morph gets back its starting weight.
Reset To ZeroEach morph is set to 0.

Presets

Data Asset UMorphCuePreset — create one with Add > Miscellaneous > Data Asset > Morph Cue Preset.

PropertyDescription
ValuesMorph targets and their weights (for example Smile 1, CheekRaise 0.6, EyeSquint 0.3).
Preview MeshEditor only: the mesh whose morph targets the picker lists.

Play a preset from a notify (Preset), from the component (Play Preset / Clear Preset) or instantly with Apply Preset. Get Value and Has Morph read a preset. Capture Morph Targets returns the current weights of a mesh, ready to store in a preset.

Modular characters

Mesh TargetsMeshes driven
This MeshThe mesh playing the animation.
This Mesh And Attached MeshesThat mesh plus every skeletal mesh attached below it (head, beard, clothes of a modular character).
All Meshes On ActorEvery skeletal mesh component of the owning actor.

When Mesh Tag is set, the extra meshes must carry that component tag; the playing mesh is always included. Meshes without the morph simply ignore it.

Mirroring

With Mirror on, the first Mirror Pair found in each morph name is swapped: Brow_L becomes Brow_R and MouthRight becomes MouthLeft. Use it on a mirrored copy of an animation, or to reuse one notify setup for both sides. Matching is case-sensitive. Mirror Morph Name does the same in Blueprint.

Morph Cue Player component

Component UMorphCueComponent — displayed as Morph Cue Player. Add it to any actor with a skeletal mesh. It ticks only while something is playing.

NodeTypeDescription
Play Morph (Morph, From, To, Duration, Easing)callPlays a morph from one weight to another.
Blend Morph To (Morph, Target, Duration, Easing)callBlends from the current weight to Target.
Play Layer (Layer, Duration, End Action)callPlays a full layer: playback, loops, window, blend mode and variation.
Play Preset (Preset, Duration, Weight, Easing)callBlends every morph of the preset to its weight.
Clear Preset (Preset, Duration, Easing)callBlends every morph of the preset back to 0.
Stop Morph / Stop All (Restore)callStops playback; Restore puts back the weights from before it started.
Is Morph Playing / Get Playing CountpurePlayback state.
Set Target Mesh / Get Target MeshcallThe mesh to drive. Default: Target Mesh Reference, else the owner's first skeletal mesh.
On Morph Finished (Morph)eventFires when a morph reaches the end of its duration (not when stopped).

Properties: Target Mesh Reference (component picker), Mesh Targets and Mesh Tag (as on the notify). Playing a morph that is already playing replaces it and continues from its current weight.

Blueprint library

Function Library UMorphCueLibrary — category MorphCue.

NodeTypeDescription
Get Morph Target NamespureAll morph target names of a mesh component.
Get Morph Target Names From AssetpureAll morph target names of a skeletal mesh asset.
Set Morph TargetscallSets many weights at once, optionally on attached or sibling meshes.
Apply PresetcallApplies a preset instantly, scaled by Weight.
Capture Morph TargetscallCurrent weights of a mesh (non-zero only by default).
Reset Morph TargetscallClears all morph weights on the target meshes.
Evaluate EasingpureAny MorphCue easing at alpha 0-1.
Evaluate LayerpureThe value a layer plays at a given time of a cue.
Mirror Morph NamepureSwaps a left/right token in a name.
Gather Target MeshescallThe meshes a cue started on a mesh would drive.
To Morph Cue Name / To NamepureAutomatic conversions between Name and Morph Cue Name.

Morph picker

Every Morph field (FMorphCueName) is shown as a text box plus a Pick button. The list is searchable and is filled from:

  • the preview mesh of the animation being edited (sequence, montage or composite), or its skeleton's preview mesh;
  • a preset's Preview Mesh;
  • the owning actor's skeletal mesh for components placed in a level.

You can always type a name. When a mesh is known, a name it does not have is shown in orange and the tooltip says so.

Debugging

Console variable MorphCue.Debug 1 prints every weight MorphCue writes on screen, tagged with its source (Notify, End, Player, Set), in development builds. It does nothing in shipping builds.

C++

#include "MorphCueComponent.h"
#include "MorphCueLibrary.h"

// Blink with the runtime player
if (UMorphCueComponent* Morphs = FindComponentByClass<UMorphCueComponent>())
{
    FMorphCueLayer Blink;
    Blink.Morph = FMorphCueName(TEXT("EyeBlink_L"));
    Blink.Playback = EMorphCuePlayback::PingPong;
    Blink.Easing = EMorphCueEasing::SineInOut;
    Blink.RandomEndOffset = 0.05f;
    Morphs->PlayLayer(Blink, 0.18f);
    Morphs->PlayPreset(SmilePreset, 0.4f);
}

// Read and write weights directly
TArray<FMorphCueValue> Current = UMorphCueLibrary::CaptureMorphTargets(GetMesh());
UMorphCueLibrary::SetMorphTargets(GetMesh(), Current, EMorphCueMeshTargets::ThisAndAttached);

The evaluation helpers are available to C++ as FMorphCueMath (Ease, Shape, Evaluate, FinalValue, Blend, Mirror, WithVariation).

Troubleshooting

SymptomCause and fix
Nothing movesCheck that the mesh really has the morph (the name turns orange when it does not) and that the notify is on a track of the animation that is playing. Try MorphCue.Debug 1.
The picker list is emptyThe animation has no preview mesh: set one in the animation editor toolbar, or type the name.
The morph ends too early or late at a different play rateSet Time Source to Animation Time (UE 5.8).
The morph stays on after the animationThat is Keep Final Value; use Restore Previous Value or Reset To Zero, or play A to B to A.
Clothes or heads of a modular character do not followSet Mesh Targets to This Mesh And Attached Meshes or All Meshes On Actor; the other meshes need morph targets with the same names.
An animation curve fights the morphA morph target curve with the same name in the playing animation also writes that weight. Drive each morph from one place: remove the curve from the animation or use a different morph.

Credits

© 2026 Alpha XP — alphaxp.net · Support: support@alphaxp.net. Built for Unreal Engine 4.27 and 5.8.