UE-Connect Documentation

1. Overview

ue-connect is a Unreal Engine 5 (UE5) connector module designed specifically for QuickUIDesign applications. It provides a complete set of hooks and context management tools, enabling ue-connect to establish bidirectional communication with UE5, particularly suitable for developing UE5 interactive interfaces based on QuickUIDesign.

QuickUIDesign is a React-based interface template that allows developers to easily create feature-rich interactive interfaces in UE5.

2. Installation

  • Copy the ue-connect library files into your project
  • Configure package.json to add the ue-connect library reference
{
  "dependencies": {
    "ue-connect": "./ue-connect",
  }
}

3. Core Features

3.1 Context Management

UEProvider and useUEContext

Provides global UE5 connection state management.

import { UEProvider, useUEContext } from 'ue-connect'

// Provide context at the app root component
function App() {
  return (
    <UEProvider>
      <YourComponent />
    </UEProvider>
  )
}

// Use context in child components
function YourComponent() {
  const { isConnected, isMobile, useMouse, setUseMouse, lastKeyAction } = useUEContext()

  return (
    <div>
      <p>Connection Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
      <p>Device Type: {isMobile ? 'Mobile' : 'Desktop'}</p>
      <p>Last Key Action: {lastKeyAction || 'None'}</p>
      <button onClick={() => setUseMouse(!useMouse)}>{useMouse ? 'Disable Mouse' : 'Enable Mouse'}</button>
    </div>
  )
}

Return Values:

  • isConnected: Indicates whether connected to the UE5 window
  • isMobile: Indicates whether it is a mobile device
  • useMouse: Indicates whether mouse events are enabled
  • setUseMouse: Function to enable/disable mouse events
  • lastKeyAction: Last key action from UE5 input events UEProvider Notes:

UEProvider internally integrates mouse event management (useUEMouse) and input event listening (useInputKeyEventListener). Child components can directly access connection status, device type, mouse status, and last key action through useUEContext.

3.2 QuickUI Custom Event System

useQuickUIEventSender and useQuickUIEventListener

Implements custom event communication between Web and UE5. Users can design their own event names and JSON formats.

  • useQuickUIEventSender is used to send events, requires specifying the event name (corresponds to backend QuickUIListenEvent)
  • useQuickUIEventListener is used to listen for events, requires specifying the event name (corresponds to backend QuickUIEventCallBack)
import { useQuickUIEventSender, useQuickUIEventListener } from 'ue-connect'

function EventSystemComponent() {
  // Send event - requires specifying event name (corresponds to backend QuickUIListenEvent)
  const sendEvent = useQuickUIEventSender('playerUpdate')

  // Listen for events from UE (corresponds to backend QuickUIEventCallBack)
  useQuickUIEventListener('gameStateChange', (event) => {
    console.log('Game state changed:', event)
    console.log('Event topic:', event.topic)
    console.log('Event payload:', event.payload)
    console.log('Timestamp:', event.timestamp)
    console.log('Event source:', event.source) // "web" or "ue"
  })

  const updatePlayer = () => {
    // Send event to UE (fire-and-forget)
    sendEvent({
      health: 100,
      ammo: 30,
      position: { x: 10, y: 20, z: 30 }
    })
  }

  return <button onClick={updatePlayer}>Update Player Data</button>
}

useQuickUIEvent Parameters:

  • fnName: Event name (corresponds to Blueprint / UMG event name)
  • Returns: A function to send events, accepting payload?: QuickEventPayload parameter

useQuickUIEventListener Parameters:

  • fnName: Event name (corresponds to Blueprint / UMG event name)
  • handler: Event handler function, receives QuickEvent object
    • event.type: Event type (fixed as "event")
    • event.topic: Event topic/name
    • event.payload: Event payload data
    • event.timestamp: Event timestamp
    • event.source: Event source ("web" or "ue")

3.3 Mouse Event Management

useUEMouse

  • Manages mouse event interaction with UE5, supports automatic detection of disabled areas.
  • data-nohit attribute: Used to mark element areas that should not trigger mouse events
import { useUEMouse } from 'ue-connect'

function MouseComponent() {
  const { useMouse, setUseMouse } = useUEMouse(true)

  return (
    <div>
      <button onClick={() => setUseMouse(!useMouse)}>{useMouse ? 'Disable Mouse Events' : 'Enable Mouse Events'}</button>

      {/* This area will not trigger mouse events */}
      <div data-nohit style={{ padding: '20px', background: '#f0f0f0' }}>
        Mouse Event Disabled Area
      </div>
    </div>
  )
}

Features:

  • Automatically detects elements with data-nohit attribute
  • Automatically disables mouse events when hovering over disabled areas
  • Supports mobile device pixel ratio adaptation

3.4 Game Control

useUEGameControl

Provides game control functions such as quitting the game and executing console commands.

import { useUEGameControl } from 'ue-connect'

function GameControlComponent() {
  const gameControl = useUEGameControl()

  return (
    <div>
      <button onClick={() => gameControl.quitGame()}>Quit Game</button>
      <button onClick={() => gameControl.executeCommand('stat fps')}>Show FPS</button>
      <button onClick={() => gameControl.clientTravel('127.0.0.1')}>Connect to Server</button>
    </div>
  )
}

Available Methods:

  • quitGame(): Quit the game
  • executeCommand(command: string): Execute console command
  • clientTravel(address: string): Client travel to specified address
  • getGraphics(): Get graphics settings
  • applyAndSaveGraphics(...): Apply and save graphics settings

3.5 Device Adaptation

useDevicePixelRatio

Automatically adapts device pixel ratio for consistent display across different devices.

import { useDevicePixelRatio } from 'ue-connect'

function ResponsiveComponent() {
  const dpr = useDevicePixelRatio()

  return (
    <div
      style={{
        width: `${100 * dpr}px`,
        height: `${50 * dpr}px`
      }}
    >
      Adaptive Element
    </div>
  )
}

3.6 Input Management

useInputBlocker

Manages input event blocking to prevent accidental interactions.

import { useInputBlocker } from 'ue-connect'

function InputComponent() {
  const { blockInput, unblockInput, isBlocked } = useInputBlocker()

  return (
    <div>
      <button onClick={blockInput}>Block Input</button>
      <button onClick={unblockInput}>Allow Input</button>
      <p>Current Status: {isBlocked ? 'Input Blocked' : 'Input Normal'}</p>
    </div>
  )
}

useInputKeyEventListener(Experimental)

Listens to key navigation events sent by UE5 engine (Up/Down/Left/Right/Confirm/Next/Previous), suitable for TV or gamepad remote control scenarios without mouse input.

Note: This is an experimental Hook. It may be removed in future versions.

import { useInputKeyEventListener } from 'ue-connect'

function NavigationComponent() {
  const { lastKeyAction } = useInputKeyEventListener({
    onKeyAction: (action) => {
      console.log('Key Action:', action)
      // action values: "Up" | "Down" | "Left" | "Right" | "Next" | "Previous" | "Select"
    }
  })

  return (
    <div>
      <p>Last Key Action: {lastKeyAction || 'None'}</p>
    </div>
  )
}

Parameters:

  • options.onKeyAction (optional): Key event callback function, receives KeyAction type parameter

Return Values:

  • lastKeyAction: Last key action, values: "Up" | "Down" | "Left" | "Right" | "Next" | "Previous" | "Select" | null

Registered Global Functions:

This Hook registers the following global functions on the window object for UE5 to call via ExecuteJs:

Global Function NameTriggered KeyAction
window.keyUp"Up"
window.keyDown"Down"
window.keyLeft"Left"
window.keyRight"Right"
window.keyNext"Next"
window.keyPrev"Previous"
window.keyEventChoose"Select"

Automatically cleans up registered global functions when component unmounts.

3.7. Low Level API

useUEEventJSON

Sends JSON-formatted event data to UE5. useUEEventJSON is a lower-level API for directly sending JSON-formatted event data to UE5.

Note: This is an earlier API. It is recommended to use the wrapped useQuickUIEventSender API instead.

import { useUEEventJSON } from 'ue-connect'

function EventComponent() {
  const triggerEvent = useUEEventJSON({ functionName: 'MyBlueprintEvent' })

  const handleClick = () => {
    triggerEvent({
      playerName: 'Player1',
      score: 100,
      level: 5,
      items: ['item1', 'item2']
    })
  }

  return <button onClick={handleClick}>Send Game Event</button>
}

Parameters:

  • functionName: Event name registered in UE5 Blueprint
  • Supports complex nested JSON data structures

useUECallback (Legacy)

A UE5 callback function that triggers on the web side to process data when the UE5 engine sends new data.

Note: This is an earlier API. It is recommended to use the wrapped useQuickUIEventListener API instead.

import { useUECallback } from 'ue-connect'

function CallbackComponent() {
  useUECallback('OnPlayerDataUpdated', (onData) => {
    console.log('Player data updated:', onData)
    // Process player data
  })

  return <div>Callback Component</div>
}

Parameters:

  • functionName: Callback function name (custom agreed function name in UE5)
  • onData: Data processing callback function, data sent by UE5

Features:

  • Performance Optimized: Only triggers callback when backend actually sends new data
  • Auto Management: Registers global function on mount, auto-cleans on unmount
  • Stable Reference: Uses ref to maintain stable callback reference, avoiding frequent re-registration

3.8 Utility Functions

filterUECallBackJSonData

A general-purpose filtering function paired with useUECallback for processing UE callback JSON data, supporting filtering and property selection.

Method Signature:

function filterUECallBackJSonData<T extends Record<string, any>>(
  data: T | undefined,
  filters: Record<string, any>
): Partial<T> | undefined

Parameters:

  • data: UE callback JSON data to process
  • filters: Filter condition object, key is property name, value is filter value or filter function

Return Value:

  • Filtered data object, returns undefined if no match

Usage Example (with useUECallback):

import { useUECallback, filterUECallBackJSonData } from 'ue-connect'
import { useState } from 'react'

function AuthComponent() {
  useUECallback(
    'OnPlayerDataUpdated',
    (data) => {
      // First check if the returned data is a JSON string
      if (typeof data === 'string') {
        try {
          data = JSON.parse(data)
        } catch {
          console.error('Invalid JSON string, treating as non-JSON:', data)
          return
        }
      }
    
      // Filter data
      const filter = filterUECallBackJSonData(data, { health: (vs: any) => vs, isAlive: (vs: any) => vs })
      
      // Callback logic processing
      console.log('Filtered data:', filter)
      /*
      Output:
      Filtered data: { health: 100, isAlive: true }
      */
    }
  )

  return (
    <div>
      <p>Health: {filter?.health || 'N/A'}</p>
      <p>Alive: {filter?.isAlive ? 'Yes' : 'No'}</p>
    </div>
  )
}

Features:

  • Flexible Filtering: Supports filtering using functions or values
  • Type Safe: Supports TypeScript generics for type consistency
  • Auto Cleanup: Returns undefined when no matching properties, convenient for subsequent processing
  • Perfect with useUECallback: Simplifies data processing logic in callback handling

4. Complete Example

import React from 'react'
import {
  UEProvider,
  useUEContext,
  useUEEventJSON,
  useUEMouse,
  useQuickUIEvent,
  useQuickUIEventListener,
  useUECallback,
  useInputKeyEventListener,
  filterUECallBackJSonData,
} from 'ue-connect'

function GameUI() {
  const { isConnected, useMouse, lastKeyAction } = useUEContext()
  const { useMouse: mouseEnabled, setUseMouse } = useUEMouse(true)
  const triggerEvent = useUEEventJSON({ functionName: 'UpdateUI' })

  // Use updated useQuickUIEvent (Old API)
  const sendPlayerEvent = useQuickUIEvent('playerAction')

  // Standard API
  const sendGameEvent = useQuickUIEventSender('gameState')

  // Listen for events from UE5
  useQuickUIEventListener('enemySpawn', (event) => {
    console.log('Enemy spawned:', event.payload)
    // Update UI state here
  })

  // Listen for UE5 key navigation events (experimental)
  useInputKeyEventListener({
    onKeyAction: (action) => {
      console.log('Key Navigation:', action)
    }
  })

  // Use optimized callback management (Old API)
  useUECallback('OnPlayerDataUpdated', (data) => {
    console.log('Player data updated:', data)
    // Process player data update
  })

  // Use filterUECallBackJSonData for data filtering (Old API)
  useUECallback(
    'OnPlayerDataUpdated', // Frontend callback function name
    (data) => {
      // Note: First check if returned data is JSON string, treat plain text as non-JSON
      if (typeof data === 'string') {
        try {
          data = JSON.parse(data)
        } catch {
          console.error('Invalid JSON string, treating as non-JSON:', data)
          return
        }
      }
    
      const filter = filterUECallBackJSonData(data, { health: (vs: any) => vs, isAlive: (vs: any) => vs })
      
      console.log('Filtered data:', filter)
    }
  )

  const handlePlayerAction = (action: string) => {
    triggerEvent({
      action,
      timestamp: Date.now(),
      playerId: 'player123'
    })

    sendPlayerEvent({
      actionType: action,
      player: 'player123'
    })
  }

  const handleGameStateChange = (state: string) => {
    sendGameEvent({
      newState: state,
      previousState: 'playing'
    })
  }

  return (
    <div className="game-ui">
      <div className="status-bar">
        <span>Status: {isConnected ? 'Connected' : 'Connecting...'}</span>
        <span>Last Key Action: {lastKeyAction || 'None'}</span>
        <button onClick={() => setUseMouse(!mouseEnabled)}>{mouseEnabled ? 'Disable' : 'Enable'} Mouse</button>
      </div>

      <div className="game-controls">
        <button onClick={() => handlePlayerAction('jump')}>Jump</button>
        <button onClick={() => handlePlayerAction('attack')}>Attack</button>
        <button onClick={() => handleGameStateChange('paused')}>Pause Game</button>
      </div>

      <div data-nohit className="no-mouse-zone">
        This area does not respond to mouse events
      </div>
    </div>
  )
}

export default function App() {
  return (
    <UEProvider>
      <GameUI />
    </UEProvider>
  )
}

5. Type Definitions

Type Definitions

// Custom event interface
interface QuickEvent<Payload = QuickEventPayload> {
  type: 'event' // Event type (fixed as "event")
  topic: string // Event topic/name
  payload?: Payload // Event payload data
  timestamp: number // Event timestamp
  source: 'web' | 'ue' // Event source
}

type QuickEventPayload = Record<string, any> | null

// Key action type
type KeyAction = "Up" | "Down" | "Left" | "Right" | "Next" | "Previous" | "Select"

Using TypeScript Types

interface QuickEvent<Payload = QuickEventPayload> {
  type: 'event'
  topic: string
  payload?: Payload
  timestamp: number
  source: 'web' | 'ue'
}

type QuickEventPayload = Record<string, any> | null

Using TypeScript Types

import { useQuickUIEvent, useQuickUIEventListener, type QuickEvent } from 'ue-connect'

// Define custom payload type
interface PlayerEvent {
  playerId: string
  health: number
  position: { x: number; y: number; z: number }
}

function TypedComponent() {
  const sendPlayerUpdate = useQuickUIEvent('playerUpdate')

  useQuickUIEventListener('playerUpdate', (event: QuickEvent<PlayerEvent>) => {
    if (event.payload) {
      console.log('Player ID:', event.payload.playerId)
      console.log('Player Health:', event.payload.health)
      console.log('Player Position:', event.payload.position)
    }
  })

  const updatePlayer = () => {
    sendPlayerUpdate({
      playerId: 'player123',
      health: 100,
      position: { x: 10, y: 20, z: 30 }
    })
  }

  return <button onClick={updatePlayer}>Update Player</button>
}

6. Best Practices

  1. Performance Optimization
  • Use data-nohit attribute wisely to avoid unnecessary mouse event handling
  • Disable mouse events when not needed to reduce performance overhead
  1. Error Handling
  • Always check isConnected status before sending events
  • Add error handling and user feedback for critical operations
  1. Event Naming
  • Use clear event naming conventions
  • Keep event names consistent between Web and UE5 sides
  1. Data Format
  • Use consistent JSON data format
  • Avoid sending excessively large data packets
  1. Type Safety
  • Use TypeScript type definitions for custom event payloads
  • Leverage type checking to avoid runtime errors