Skip to main content

What Problem Does This Solve?

Delegates let you react to LCK events in real-time:
  • Recording started/stopped
  • Save progress updates
  • Button interactions
  • Camera mode changes
  • Audio callbacks
Instead of polling state every frame, you bind handlers that fire when events occur. This keeps your code clean and responsive.

When to Use This

Reference this when:
  • Building custom recording UI
  • Handling recording lifecycle events
  • Responding to user interactions
  • Processing audio data
  • Tracking save progress

Delegate Types

LCK uses two kinds of delegates:
Audio delegates are SINGLE delegates (not multicast). Use BindLambda(), not AddLambda(). Each bind replaces the previous one.
DataModel delegates are non-dynamic multicast. Most delegates on ULCKTabletDataModel (camera mode, mic state, video quality, recording state) use DECLARE_MULTICAST_DELEGATE, not DECLARE_DYNAMIC_MULTICAST_DELEGATE. Bind with AddUObject() or AddLambda(), not AddDynamic().

Recording Lifecycle Delegates

FOnRecordingSaveFinished

What it’s for: Know when recording save completes
Declared on: ULCKService Parameters:
  • Success (bool) — True if save succeeded, false on error
Usage:

FOnRecordingSaveProgress

What it’s for: Update progress bar during save
Declared on: ULCKService Parameters:
  • Progress (float) — Value from 0.0 (start) to 1.0 (complete)
Usage:

FOnRecordingError

What it’s for: Handle recording errors with context
Declared on: ULCKService Parameters:
  • ErrorMessage (FString) — Human-readable error description
  • ErrorCode (int32) — Numeric error code (see ELCKError)
Usage:

Camera & Settings Delegates

FOnTabletCameraModeChanged

What it’s for: React to camera mode switches
Declared on: ULCKTabletDataModel Parameters:
  • UClass* — The new camera mode class (e.g., ULCKSelfieCameraMode, ULCKFirstPersonCameraMode, ULCKThirdPersonCameraMode)
This is a non-dynamic multicast delegate. Use AddUObject() or AddLambda(), not AddDynamic().
Usage:

FOnMicStateChanged

What it’s for: Update UI when mic state changes
Declared on: ULCKTabletDataModel Parameters:
  • ELCKMicState — New microphone state (On, Off, No_Access)
This is a non-dynamic multicast delegate. Use AddUObject() or AddLambda(), not AddDynamic().
Usage:

FOnVideoQualityChanged

What it’s for: React to quality profile changes
Declared on: ULCKTabletDataModel
This is a non-dynamic multicast delegate. Use AddUObject() or AddLambda(), not AddDynamic().
Usage:

FOnRecordStateChange

What it’s for: React to recording state changes on the DataModel
Declared on: ULCKTabletDataModel
This is a non-dynamic multicast delegate. Use AddUObject() or AddLambda(), not AddDynamic().
Usage:

FOnScreenOrientationChanged

What it’s for: React to screen orientation changes
Declared on: ULCKTabletDataModel
This is a non-dynamic multicast delegate. Use AddUObject() or AddLambda(), not AddDynamic().
Usage:

UI Interaction Delegates

FOnTapStarted

What it’s for: Handle button presses
Usage:
LCK buttons include automatic 0.25s cooldown. Don’t add your own debouncing.

FOnStepperValueChanged

What it’s for: Handle stepper control changes (increment/decrement buttons)
Parameters:
  • NewValue (int8) — Direction: -1 (decrease) or +1 (increase)
Usage:

FOnPad2DChanged

What it’s for: Handle 2D directional pad input
Parameters:
  • NewValue (FIntPoint) — Direction as (X, Y) where values are -1, 0, or +1
Usage:

Audio Delegates

FOnRenderAudioDelegate

What it’s for: Process raw audio data from audio sources
Parameters:
  • PCM (TArrayView<const float>) — Interleaved audio samples (32-bit float)
  • Channels (int32) — Number of channels (typically 2 for stereo)
  • SampleRate (int32) — Audio sample rate in Hz (typically 48000)
  • Source (ELCKAudioChannel) — Audio source type (Game, Microphone, VoiceChat)
This is a SINGLE delegate (not multicast). Use BindLambda(), not AddLambda(). Each bind replaces the previous one.Audio callbacks may come from different threads. Use AsyncTask(ENamedThreads::GameThread, ...) if accessing game thread objects.
Usage:
Fire the delegate (from audio source implementation):

Async Operation Delegates

FOnLCKRecorderBoolResult

What it’s for: Handle async operation results
Usage:

FOnLCKRecorderProgress

What it’s for: Track save/encoding progress
Usage:

Binding Patterns

Dynamic Delegates (Blueprint-Compatible)

Used for FOnRecordingSaveFinished, FOnRecordingSaveProgress, FOnRecordingError, and UI delegates like FOnTapStarted.

Non-Dynamic Multicast (C++ Only)

Used for DataModel delegates like FOnTabletCameraModeChanged, FOnMicStateChanged, FOnVideoQualityChanged, FOnRecordStateChange.

Lambda Binding (C++ Only)


Removing Bindings


Complete Example: Recording UI


Key Takeaways

Use delegates for events — Don’t poll state every frame
Dynamic vs non-dynamic matters — DataModel delegates use AddUObject/AddLambda, Service delegates use AddDynamic
Audio delegates are SINGLE — Use BindLambda, not AddLambda
Thread safety matters — Audio callbacks may come from any thread
Remove bindings on cleanup — Prevent dangling pointers
Dynamic delegates for Blueprint — Use UFUNCTION handlers with AddDynamic