vue3与UE55连接与双向通信

9 阅读3分钟

1、介绍

在数字孪生中,通常会用到ue5虚幻引擎与浏览器之间的通信与像素流送。此时我们可以通过官方推荐包来实现快速通信

  • @epicgames-ps/lib-pixelstreamingfrontend-ue5.4: ^1.1.5
  • @epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.4: ^1.0.5

依赖包说明

1. @epicgames-ps/lib-pixelstreamingfrontend-ue5.4

版本: ^1.1.5

作用: 这是 Pixel Streaming 的核心库,提供了与 UE5 像素流送服务器通信的底层功
能。

主要功能模块

Config 类

配置管理类,用于设置连接参数和初始化选项。

核心功能:

  • 管理信令服务器连接配置
  • 设置视频/音频参数
  • 控制输入行为(鼠标、键盘、触摸)
  • 管理 URL 参数解析
  • 提供标志位(Flags)和数值参数(Numeric Parameters)配置
PixelStreaming 类

核心流送类,负责建立 WebRTC 连接、处理视频流、音频流和数据通道。

核心功能:

  • 建立和管理 WebRTC 连接
  • 处理信令服务器通信
  • 管理视频/音频流
  • 提供数据通道通信
  • 事件发射和监听
  • 输入设备管理(鼠标、键盘、触摸、游戏手柄)
数据通道相关类
  • InitialSettings: 初始设置数据结构
  • AggregatedStats: 聚合统计数据
  • MessageStreamerList: 流送器列表消息

2、代码实现

基于vue3封装了应用型组件,具体代码如下

<template>
  <div
    ref="playerContainer"
    id="playercontainer"
    style="width: 100%; height: 100%; position: relative"
  >
    <!-- 默认内容 层级在视频流中 -->
    <slot />
  </div>
</template>

<script setup>
import {
  Config,
  PixelStreaming,
} from '@epicgames-ps/lib-pixelstreamingfrontend-ue5.4'
import {
  Application,
  PixelStreamingApplicationStyle,
  UIElementCreationMode,
} from '@epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.4'

import { onMounted, ref, defineProps, onUnmounted } from 'vue'
import { emitter } from '@/common/eventBus/index.js'
let application = null
let pixelStreaming = null
const playerContainer = ref('')
// props定义
const props = defineProps({
  pixelConfig: {
    type: Object,
    default: () => {},
  },
})

// emit定义
// 定义 emits
const emit = defineEmits(['ueSendEvent'])

// 初始化挂载dom
onMounted(() => {
  initPixelStreaming()
  emitter.on('sendMessageToUE5', sendMessageToUE5)
})
// 初始化 Pixel Streaming
const initPixelStreaming = () => {
  const PixelStreamingApplicationStyles = new PixelStreamingApplicationStyle()
  PixelStreamingApplicationStyles.applyStyleSheet()
  // 创建配置 - 不再隐藏UI
  const config = new Config({
    useUrlParams: true,
    // useDefaultConfig: false, // 禁用默认配置

    initialSettings: {
      // useUrlParams: true,
      ss: '具体的信令服务器连接地址', //--本机地址
      HoveringMouse: true, //&ControlScheme结合是否显示鼠标j
      ControlScheme: true,
      ForceMonoAudio: true,
      AutoPlayVideo: true, //自动播放--有些地方浏览器会因静音导致无法自动播放
      StartVideoMuted: true, // 保持静音以提高自动播放成功率
      AutoConnect: true, // 添加自动连接
      WaitForStreamer: true, // 添加等待流媒体服务器
      TouchInput: false, //禁止鼠标跟随视角
      HideUI: true,
      ...props.pixelConfig, // 配置覆盖
    },
  })

  // 创建 Pixel Streaming 实例
  pixelStreaming = new PixelStreaming(config)

  // 创建应用程序UI并关联 Pixel Streaming 实例
  application = new Application({
    stream: pixelStreaming,
    onColorModeChanged: (isLightMode) =>
      PixelStreamingApplicationStyles.setColorMode(isLightMode),
    // 设置按钮
    settingsPanelConfig: {
      isEnabled: true,
      visibilityButtonConfig: { creationMode: UIElementCreationMode.Disable },
    },
    // 状态按钮
    statsPanelConfig: {
      isEnabled: true,
      visibilityButtonConfig: { creationMode: UIElementCreationMode.Disable },
    },
    // 禁用全屏按钮
    fullScreenControlsConfig: { creationMode: UIElementCreationMode.Disable },
  })

  // 将应用元素附加到容器
  if (playerContainer.value) {
    playerContainer.value.appendChild(application.rootElement)
  }

  //   使用 setTimeout 确保面板已经创建完成后再隐藏
  setTimeout(() => {
    if (application.settingsPanel) {
      application.settingsPanel.hide()
    }
    // const timer = setInterval(() => {
    //   // 设置视频静音
    // if (video) {
    playerContainer.value?.setAttribute('muted', true)
    // clearInterval(timer)
    // }
    // })
    application.showDisconnectOverlay('等待连接....')
    application.showTextOverlay('连接失败')
    if (application.statsPanel) {
      application.statsPanel.hide()
    }

    // 发送初始化事件
    emitter.emit('sendMessageToUE5', {
      type: 'Initialization',
      id: 'StateInitialization',
    })
  }, 100)

  // 监听ue5发送事件
  application.stream.addResponseEventListener('handle_responses', ueSendEvent)
}
//   发送后ue事件
const ueSendEvent = (response) => {
  console.log('responseresponseresponse', response)
  const data = JSON.parse(response)
  emitter.emit('ueSendEvent', data)
}

// 向UE5发送消息的方法
const sendMessageToUE5 = (message) => {
  console.log('发送消息到ue', message)
  // 其他消息正常发送到UE5
  if (typeof pixelStreaming?.emitUIInteraction === 'function') {
    pixelStreaming.emitUIInteraction(message)
  } else {
    console.error('pixelStreaming.emitUIInteraction 方法不可用')
  }
}
</script>

这里主要有以下几个注意点:

  • application.stream.addResponseEventListener('handle_responses', ueSendEvent) 监听ue5发送事件
    
  •  pixelStreaming.emitUIInteraction(message) 向ue5发送消息
    
  •  我这里用的事件总线mitt跨组件通信,可根据实际场景更换