-
Notifications
You must be signed in to change notification settings - Fork 6
Live Funcs
Live ProcessEvent call profiler — perform an in-game action and see exactly which UFunctions fired, ranked so the causal entry point rises to the top.
This is behaviour-based UFunction discovery. It hooks UObject::ProcessEvent and counts every UFunction the game dispatches during a Start/Stop recording window. Where the Interesting Functions tab scores functions by their name, this tab scores them by their behaviour: instead of guessing which function opens a shop, you actually open the shop, and the tab shows which UFunctions really fired. It finds game-specific functions whose names are unguessable, and ranks them so the function that caused the action floats to the top.
Starting a recording forces the game-thread ProcessEvent hook to install, so no prior invoke is needed — just open the tab and press Start.
- Set Baseline: press Start, stand idle a few seconds, press Stop, then click Set Baseline. This captures an idle reference frame (the per-frame Tick/animation noise) and turns on Diff vs baseline mode.
- Record the action: press Start, ALT-TAB to the game, perform exactly ONE action (open a shop, dash, attack), ALT-TAB back, press Stop.
- Read the diff: rows that fired only during the action are tagged NEW (green) in the Δ vs base column. Turn on New/changed only to hide everything that also fired at baseline — the unchanged per-frame Tick noise disappears.
- Hide UI widgets: opening a menu or shop creates its widget, so all of that widget's own methods fire at once and flood the list (tagged UI in the Kind column). Turn on Hide UI widgets to drop them — what remains is the persistent opener (living on a PlayerController, a UI-manager subsystem, or an interaction component).
-
Hide events/delegates:
On*/ callback functions (tagged Event or Deleg in the Type column) are reactions the engine fires at the game, not functions you call to make the action happen. Turn on Hide events/delegates to leave only the imperative Call functions. - Earliest first: an action's entry point fires before the reactions it triggers, so turn on Earliest first (sort by the Order column, ascending) to float the true opener to the top. This is the causal, name-independent signal.
- Act: click Live on a row to open that function in Live-Walker on a live instance (it falls back to Class Struct if no instance is live), where you can invoke it. Name copies the function name.
The workflow above finds the function behind a one-off action. The inverse finds a function that fires on a repeating timer — the callback driving a cooldown, a respawn, a damage-over-time tick, or a periodic AI decision.
- Get into the state you want to inspect (e.g. stand in a damage-over-time area, or somewhere a value regenerates on a timer).
- Press Start and stand idle for ~15–20 seconds — long enough for the slowest timer of interest to fire at least ~4 times.
- Press Stop, then turn on Periodic only.
What remains are functions firing at a regular cadence outside the per-frame Tick band — tagged Timer in the Kind column, with the measured interval in the Period column. The tab measures each function's inter-arrival regularity, so per-frame Tick (and irregular, input-driven functions) are filtered out. Example: an idle recording on one UE4 game flagged a Blueprint's TryAttackEnable at a steady ~325 ms — a real ~3 Hz timer — out of ~90 functions.
Limit: only UFUNCTION-bound timers are visible (a Blueprint Set Timer by Event / Function Name, or a dynamic-delegate timer). A native C++ SetTimer(this, &UClass::Method) calls its callback directly and bypasses ProcessEvent, so it never appears here — the same fundamental limit as the rest of this tab.
| Column | Meaning |
|---|---|
| Order | Call-stream position of the function's first fire. Lower = earlier = more likely the entry point. |
| Calls | How many times the function fired during the window. |
| Δ vs base | NEW if it never fired at baseline, or +N if it fired more than baseline. |
| Type | Event / Deleg / Call / native — derived from FunctionFlags. |
| Kind | Timer marks a periodic timer-cadence callback; UI marks a transient widget method. |
| Class | The class that owns the function. |
| Function | The UFunction name. |
| Params | The function's parameters. |
| Period | For a periodic function, the measured firing interval (e.g. 325 ms, 1 s); blank otherwise. |
A keyword filter box narrows the list (space = AND over function + class name). Refresh re-pulls the current counts and Clear resets the recording. Live and Name are per-row actions.
The ProcessEvent hook only observes reflected / Blueprint-dispatched calls. A native C++ → native C++ call is invisible to it. If turning on Hide events/delegates empties the list, the action's real entry point is native (or the panel had not fully appeared yet — record straight through until it is on screen). This is the fundamental limit of behaviour-based discovery, not a bug.
For most UE games (Blueprint-driven gameplay) the action's function is found directly. Real example: one game opened its shop via a native C++ call, so only its Blueprint event callbacks (On*) were visible; another game's shop was a streamed menu level and surfaced cleanly.
If Start reports that the PE hook could not install — counts stay at 0 even though the game is running — MinHook could not place its trampoline near ProcessEvent in this process. Change to another map or scene and press Start again: a level reload reshuffles memory and almost always frees the space. If it persists, restart the game and re-inject. This is unrelated to whether the game is supported — the same game hooks fine in a fresh or differently-loaded process. Clicking Start again also retries the install.
Recording is opt-in and near-zero cost when idle; leaving the tab auto-stops any live recording. This tab is pipe-only (no CE Lua / .CT).
- Interesting-Funcs-and-Props — the name-based counterpart for function discovery
- Live-Walker to invoke a found function on a live instance
- Console for UFUNCTION(exec) command discovery