简体中文
English
简体中文
English

快速导览

ue-connect 文档

#UE-Connect 文档

#一、概述

ue-connect 是一个专为QuickUIDesign 应用设计的 Unreal Engine 5 (UE5) 连接器模块。它提供了一套完整的 hooks 和上下文管理工具,使 ue-connect 能够与 UE5 进行双向通信,特别适用于基于 QuickUIDesign 的 UE5 交互界面开发。

QuickUIDesign是一个基于React设计的界面模板,使开发者能够方便地在UE5中创建交互功能丰富的界面。

#二、安装

  • 拷贝 ue-connect 库文件到项目中
  • 配置package.json,添加ue-connect库的引用
{
  "dependencies": {
    "ue-connect": "./ue-connect",
  }
}

#三、核心功能

#1. 上下文管理

#UEProvider 和 useUEContext

提供全局的 UE5 连接状态管理。

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

// 在应用根组件中提供上下文
function App() {
  return (
    <UEProvider>
      <YourComponent />
    </UEProvider>
  )
}

// 在子组件中使用上下文
function YourComponent() {
  const { isConnected, isMobile, useMouse, setUseMouse, lastKeyAction } = useUEContext()

  return (
    <div>
      <p>连接状态: {isConnected ? '已连接' : '未连接'}</p>
      <p>设备类型: {isMobile ? '移动设备' : '桌面设备'}</p>
      <p>最近按键: {lastKeyAction || '无'}</p>
      <button onClick={() => setUseMouse(!useMouse)}>{useMouse ? '禁用鼠标' : '启用鼠标'}</button>
    </div>
  )
}

返回值说明:

  • isConnected: 表示是否已连接到 UE5 窗口
  • isMobile: 表示是否为移动设备
  • useMouse: 表示是否启用鼠标事件
  • setUseMouse: 用于设置是否启用鼠标事件的函数
  • lastKeyAction: 最近一次按键操作,来自 UE5 的输入事件。值为 "Up" | "Down" | "Left" | "Right" | "Next" | "Previous" | "Select" | null

UEProvider 说明:

UEProvider 内部集成了鼠标事件管理 (useUEMouse) 和输入事件监听 (useInputKeyEventListener),子组件通过 useUEContext 可直接获取连接状态、设备类型、鼠标状态及最近按键操作。

#2. QuickUI自定义事件系统

#useQuickUIEventSender 和 useQuickUIEventListener

实现 Web 与 UE5 之间的自定义事件通信,用户可以设计自己的事件名称和Json格式。

  • useQuickUIEventSender 用于发送事件,需要指定事件名称(对应后端QuickUIListenEvent接收)
  • useQuickUIEventListener 用于监听事件,需要指定事件名称(对应后端QuickUIEventCallBack发送)
import { useQuickUIEvent, useQuickUIEventListener } from 'ue-connect'

function EventSystemComponent() {
  // 发送事件 - 需要指定事件名称(对应后端QuickUIListenEvent)
  const sendEvent = useQuickUIEventSender('playerUpdate')

  // 监听事件 - 监听来自 UE 的事件(对应后端QuickUIEventCallBack)
  useQuickUIEventListener('gameStateChange', (event) => {
    console.log('游戏状态改变:', event)
    console.log('事件主题:', event.topic)
    console.log('事件载荷:', event.payload)
    console.log('时间戳:', event.timestamp)
    console.log('事件源:', event.source) // "web" 或 "ue"
  })

  const updatePlayer = () => {
    // 发送事件到 UE(fire-and-forget)
    sendEvent({
      health: 100,
      ammo: 30,
      position: { x: 10, y: 20, z: 30 }
    })
  }

  return <button onClick={updatePlayer}>更新玩家数据</button>
}

useQuickUIEvent 参数说明:

  • fnName: 事件名称(对应 Blueprint / UMG 事件名)
  • 返回值:发送事件的函数,接受 payload?: QuickEventPayload 参数

useQuickUIEventListener 参数说明:

  • fnName: 事件名称(对应 Blueprint / UMG 事件名)
  • handler: 事件处理函数,接收 QuickEvent 对象
    • event.type: 事件类型(固定为 "event")
    • event.topic: 事件主题/名称
    • event.payload: 事件载荷数据
    • event.timestamp: 事件时间戳
    • event.source: 事件源("web" 或 "ue")

#3. 鼠标事件管理

#useUEMouse

  • 管理鼠标事件与 UE5 的交互,支持自动检测禁用区域。
  • data-nohit 属性:用于标记不触发鼠标事件的元素区域
import { useUEMouse } from 'ue-connect'

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

  return (
    <div>
      <button onClick={() => setUseMouse(!useMouse)}>{useMouse ? '禁用鼠标事件' : '启用鼠标事件'}</button>

      {/* 这个区域不会触发鼠标事件 */}
      <div data-nohit style={{ padding: '20px', background: '#f0f0f0' }}>
        鼠标事件禁用区域
      </div>
    </div>
  )
}

特性:

  • 自动检测带有 data-nohit 属性的元素
  • 当鼠标悬停在禁用区域时自动禁用鼠标事件
  • 支持移动设备像素比适配

#4. 游戏控制

#useUEGameControl

提供游戏控制功能,如退出游戏、执行控制台命令等。

import { useUEGameControl } from 'ue-connect'

function GameControlComponent() {
  const gameControl = useUEGameControl()

  return (
    <div>
      <button onClick={() => gameControl.quitGame()}>退出游戏</button>
      <button onClick={() => gameControl.executeCommand('stat fps')}>显示FPS</button>
      <button onClick={() => gameControl.clientTravel('127.0.0.1')}>连接到服务器</button>
    </div>
  )
}

可用方法:

  • quitGame(): 退出游戏
  • executeCommand(command: string): 执行控制台命令
  • clientTravel(address: string): 客户端旅行到指定地址
  • getGraphics(): 获取图形设置
  • applyAndSaveGraphics(...): 应用并保存图形设置

#5. 设备适配

#useDevicePixelRatio

自动适配设备像素比,确保在不同设备上显示一致。

import { useDevicePixelRatio } from 'ue-connect'

function ResponsiveComponent() {
  const dpr = useDevicePixelRatio()

  return (
    <div
      style={{
        width: `${100 * dpr}px`,
        height: `${50 * dpr}px`
      }}
    >
      自适应元素
    </div>
  )
}

#6. 输入管理

#useInputBlocker

管理输入事件阻止,防止意外交互。

import { useInputBlocker } from 'ue-connect'

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

  return (
    <div>
      <button onClick={blockInput}>阻止输入</button>
      <button onClick={unblockInput}>允许输入</button>
      <p>当前状态: {isBlocked ? '输入已阻止' : '输入正常'}</p>
    </div>
  )
}

#### `useInputKeyEventListener`

监听 UE5 引擎发送的按键导航事件(上/下/左/右/确认/上一页/下一页),适用于 TV 端或手柄遥控器等非鼠标输入场景。

```tsx
import { useInputKeyEventListener } from 'ue-connect'

function NavigationComponent() {
  const { lastKeyAction } = useInputKeyEventListener({
    onKeyAction: (action) => {
      console.log('按键事件:', action)
      // action 值为 "Up" | "Down" | "Left" | "Right" | "Next" | "Previous" | "Select"
    }
  })

  return (
    <div>
      <p>最近按键: {lastKeyAction || '无'}</p>
    </div>
  )
}

参数说明:

  • options.onKeyAction (可选): 按键事件回调函数,接收 KeyAction 类型参数

返回值说明:

  • lastKeyAction: 最近一次按键操作,值为 "Up" | "Down" | "Left" | "Right" | "Next" | "Previous" | "Select" | null

注册的全局函数:

该 Hook 会在 window 对象上注册以下全局函数供 UE5 通过 ExecuteJs 调用:

全局函数名触发的 KeyAction
window.keyUp"Up"
window.keyDown"Down"
window.keyLeft"Left"
window.keyRight"Right"
window.keyNext"Next"
window.keyPrev"Previous"
window.keyEventChoose"Select"

组件卸载时自动清理所注册的全局函数。

#7.底层API

useUEEventJSON是更底层的API,用于直接发送JSON格式的事件数据到UE5。
例如:useUEEventJSON,基于useUEEventJSON封装

#useUEEventJSON

向 UE5 发送 JSON 格式的事件数据。

import { useUEEventJSON } from 'ue-connect'

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

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

  return <button onClick={handleClick}>发送游戏事件</button>
}

参数说明:

  • functionName: UE5 蓝图中注册的事件名称
  • 支持复杂嵌套的 JSON 数据结构

#useUECallback(Old)

优化的回调管理,只在后端真正发送新数据时触发,避免不必要的重复调用。

import { useUECallback } from 'ue-connect'

function CallbackComponent() {
  useUECallback('OnPlayerDataUpdated', (onData) => {
    console.log('玩家数据更新:', onData)
    // 处理玩家数据
  })

  return <div>回调组件</div>
}

参数说明:

  • functionName: 回调函数名称(在UE5中自定义约定的调用函数名)
  • onData: 数据处理回调函数,UE5发送的数据

特性说明:

  • 优化性能:只在后端真正发送新数据时触发回调
  • 自动管理:组件挂载时注册全局函数,卸载时自动清理
  • 稳定引用:使用ref保持回调引用稳定,避免频繁重新注册

#8.辅助函数

#filterUECallBackJSonData

这是已给与useUECallback配套的通用筛选函数,用于处理 UE 回调的 Json 序列,支持过滤和筛选属性。

方法签名:

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

参数说明:

  • data: UE 回调的待处理Json数据
  • filters: 筛选条件对象,键为属性名,值为筛选值或筛选函数

返回值:

  • 筛选后的数据对象,如无匹配则返回 undefined

使用示例(结合 useUECallback):

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

function AuthComponent() {
  const [serverURL, setServerURL] = useState('')
  const [title, setTitle] = useState('')

  useUECallback(
    'OnPlayerDataUpdated', // 前端回调函数名称
    (data) => {
      // 注意传回的数据先判断是否为json字符串,普通字符按非json处理
      if (typeof data === 'string') {
        try {
          data = JSON.parse(data)
        } catch {
          console.error('无效的 JSON 字符串按非json处理:', data)
          return
        }
      }
    
      // 过滤数据
      const filter = filterUECallBackJSonData(data, { health: (vs: any) => vs, isAlive: (vs: any) => vs })
      
      // 回调逻辑处理
      console.log('筛选后的数据:', filter)
      /*
      打印结果:
      筛选后的数据: { health: 100, isAlive: true }
      */
    }
  )

  return (
    <div>
      <p>健康值: {filter?.health || '未指定'}</p>
      <p>是否存活: {filter?.isAlive ? '是' : '否'}</p>
    </div>
  )
}

特性说明:

  • 灵活筛选:支持使用函数或值进行筛选
  • 类型安全:支持 TypeScript 泛型,保持类型一致性
  • 自动清理:无匹配属性时返回 undefined,便于后续处理
  • 与 useUECallback 完美结合:在回调处理中使用,简化数据处理逻辑

#四、完整示例

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' })

  // 使用更新后的 useQuickUIEvent
  const sendPlayerEvent = useQuickUIEvent('playerAction')
  const sendGameEvent = useQuickUIEvent('gameState')

  // 监听来自 UE5 的事件
  useQuickUIEventListener('enemySpawn', (event) => {
    console.log('敌人生成:', event.payload)
    // 可以在这里更新 UI 状态
  })

  // 监听 UE5 按键导航事件(适用于 TV 端或手柄遥控器)
  useInputKeyEventListener({
    onKeyAction: (action) => {
      console.log('按键导航:', action)
    }
  })

  // 使用优化的回调管理
  useUECallback('OnPlayerDataUpdated', (data) => {
    console.log('玩家数据更新:', data)
    // 处理玩家数据更新
  })

  // 使用filterUECallBackJSonData进行数据筛选
  useUECallback(
    'OnPlayerDataUpdated', // 前端回调函数名称
    (data) => {
      // 注意传回的数据先判断是否为json字符串,普通字符按非json处理
      if (typeof data === 'string') {
        try {
          data = JSON.parse(data)
        } catch {
          console.error('无效的 JSON 字符串按非json处理:', data)
          return
        }
      }
    
      // 过滤数据
      const filter = filterUECallBackJSonData(data, { health: (vs: any) => vs, isAlive: (vs: any) => vs })
      
      // 回调逻辑处理
      console.log('筛选后的数据:', filter)
      /*
      打印结果:
      筛选后的数据: { health: 100, isAlive: true }
      */
    }
  )

  const handlePlayerAction = (action: string) => {
    // 发送 JSON 事件到 UE5
    triggerEvent({
      action,
      timestamp: Date.now(),
      playerId: 'player123'
    })

    // 发送 QuickUI 事件
    sendPlayerEvent({
      actionType: action,
      player: 'player123'
    })
  }

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

  return (
    <div className="game-ui">
      <div className="status-bar">
        <span>状态: {isConnected ? '已连接' : '连接中...'}</span>
        <span>最近按键: {lastKeyAction || '无'}</span>
        <button onClick={() => setUseMouse(!mouseEnabled)}>{mouseEnabled ? '禁用' : '启用'}鼠标</button>
      </div>

      <div className="game-controls">
        <button onClick={() => handlePlayerAction('jump')}>跳跃</button>
        <button onClick={() => handlePlayerAction('attack')}>攻击</button>
        <button onClick={() => handleGameStateChange('paused')}>暂停游戏</button>
      </div>

      {/* 鼠标事件禁用区域 */}
      <div data-nohit className="no-mouse-zone">
        此区域不响应鼠标事件
      </div>
    </div>
  )
}

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

#五、类型定义

#类型定义

// 按键操作类型
type KeyAction = "Up" | "Down" | "Left" | "Right" | "Next" | "Previous" | "Select"

// 自定义事件接口
interface QuickEvent<Payload = QuickEventPayload> {
  type: 'event' // 事件类型(固定为 "event")
  topic: string // 事件主题/名称
  payload?: Payload // 事件载荷数据
  timestamp: number // 事件时间戳
  source: 'web' | 'ue' // 事件源
}

type QuickEventPayload = Record<string, any> | null

#使用 TypeScript 类型

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

// 定义自定义载荷类型
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('玩家ID:', event.payload.playerId)
      console.log('玩家血量:', event.payload.health)
      console.log('玩家位置:', event.payload.position)
    }
  })

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

  return <button onClick={updatePlayer}>更新玩家</button>
}

#六、最佳实践

  1. 性能优化
  • 合理使用 data-nohit 属性避免不必要的鼠标事件处理
  • 在不需要时禁用鼠标事件以减少性能开销
  1. 错误处理
  • 始终检查 isConnected 状态再发送事件
  • 对重要操作添加错误处理和用户反馈
  1. 事件命名
  • 使用清晰的事件命名规范
  • 保持 Web 端和 UE5 端事件名称一致
  1. 数据格式
  • 使用一致的 JSON 数据格式
  • 避免发送过大的数据包
  1. 类型安全
  • 使用 TypeScript 类型定义自定义事件载荷
  • 充分利用类型检查避免运行时错误

#七、注意事项

  • 本库专为 UE5 设计,不适用于其他游戏引擎
  • 需要在 UE5 项目中正确配置 JavaScript 接口
  • 确保浏览器支持所需的现代 JavaScript 特性
  • 商业授权,未经授权严禁复制、分发或使用

#八、支持与联系

  • 开发者: MarcoTin
  • 联系方式: https://space.bilibili.com/74228375
  • 版权所有 © 2025 QuickUICORE