首页 > 编程语言 >Unity+QT, 如何把Unity打包出的exe嵌入QT程序中,并且使用Socket进行交互

Unity+QT, 如何把Unity打包出的exe嵌入QT程序中,并且使用Socket进行交互

时间:2024-08-30 16:23:04浏览次数:14  
标签:exe QT void Unity client QString data

文章目录

概要

在 VR 开发中,常常需要桌面窗口和 VR 头盔使用者进行交互。通过将 Unity制作的 VR 程序嵌入到 QT 应用程序窗口中,并使用 Socket进行通信,可以实现这种交互。本文将介绍如何实现这一功能。

前期准备

  1. Unity 项目打包 首先,在 Unity 中开发并打包您的项目为可执行文件(EXE)。确保您已经测试过独立运行的 EXE 并且一切正常。

  2. QT 环境设置 安装并配置好 QT 开发环境。如果您还没有 QT 安装,可以访问 QT 官方网站 下载和安装。

QT 与 Unity 的 Socket 通信

  1. QT 服务器设置 在 QT 中,使用 QUdpSocket 创建一个 UDP 服务器来接收来自 Unity 的数据,在QT程序初始化时用QProcess启动Unity程序,并且等待Unity程序连接,Unity程序连接后获取Unity程序的窗口句柄,并把这个窗口嵌入到QT中:
#include <QPushButton>
#include <QVBoxLayout>
#include <QtNetwork>
#include "QProcess"
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
    {
        QUdpSocket* socket = new QUdpSocket(this);
		socket->bind(QHostAddress("127.0.0.1"), 6060);
		connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));

		QProcess* process = new QProcess(this);
		QString cmd = "path/to/your/VRUnityApp.exe";
		process->start(cmd, QStringList() << "");
 
        QVBoxLayout *layout = new QVBoxLayout;
        QWidget *centralWidget = new QWidget(this);
        centralWidget->setLayout(layout);
        setCentralWidget(centralWidget);

        QPushButton *switchSceneButton = new QPushButton("Switch Scene", this);
        QPushButton *createObjectButton = new QPushButton("Create Object", this);

        layout->addWidget(switchSceneButton);
        layout->addWidget(createObjectButton);

        connect(switchSceneButton, &QPushButton::clicked, [server]() {
            sendData("switch_scene");
        });

        connect(createObjectButton, &QPushButton::clicked, [server]() {
            sendData("create_object");
        });
    }
    void sendData(const QString& data)
    {
    	for (int i = 0; i < m_client.count(); i++) {
			QString str = m_client.at(i);
			QStringList list = str.split(":");
			QByteArray buffer;
			buffer = data.toUtf8();
			socket->writeDatagram(buffer, QHostAddress(list.at(0)), list.at(1).toInt());
		}
    }
    void OnDataRecived(const QString& msg)
    {
    	if (msg == "Connect")
		{
			WId wid = (WId)FindWindow(L"XXXXX", NULL);//获取窗口句柄
			m_window = QWindow::fromWinId(wid);
			m_window->setFlags(m_window->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
	
			QWidget* m_widget;
			m_widget = QWidget::createWindowContainer(m_window, this);
			ui->containerWidget->layout()->addWidget(m_widget);
		}
    }
 private slots:
    void readData()
    {
    	QHostAddress host;
		quint16 port;
		QByteArray data;
		QString buffer;
		
		while (socket->hasPendingDatagrams()) {
			data.resize(socket->pendingDatagramSize());
			socket->readDatagram(data.data(), data.size(), &host, &port);
		
			buffer = QString(data);
			OnDataRecived(buffer);
			QString ip = host.toString();
			ip = ip.replace("::ffff:", "");
			if (ip.isEmpty()) {
				continue;
			}
		
			QString str = QString("[%1:%2] %3").arg(ip).arg(port);
		
			//先过滤重复的
			str = QString("%1:%2").arg(ip).arg(port);
			for (int i = 0; i < m_client.count(); i++) {
				if (str == m_client.at(i)) {
					return;
				}
			}
			//添加到列表
			m_client.push_back(str);
		}
    }
};
  1. Unity 客户端设置 在 Unity 中,使用 System.Net.Sockets.UdpClient 创建一个 UDP 客户端,并向 QT 服务器发送数据:
public class UnityClient : MonoBehaviour
{
    private UdpClient client;

    void Start()
    {
        client = new UdpClient();
        SendMessageToServer("Connect");
        client.BeginReceive(OnReceive, null);
    }

    void SendMessageToServer(string message)
    {
        byte[] data = Encoding.UTF8.GetBytes(message);
        client.Send(data, data.Length, "127.0.0.1", 12345);
    }

	private void OnReceive(IAsyncResult ar)
    {
        IPEndPoint endpoint = new IPEndPoint(System.Net.IPAddress.Any, 54321);
        byte[] data = client.EndReceive(ar, ref endpoint);
        string command = Encoding.UTF8.GetString(data);

        Debug.Log("Received command: " + command);

        // 根据命令执行相应的操作
        if (command == "switch_scene")
        {
            SwitchScene();
        }
        else if (command == "create_object")
        {
            CreateObject();
        }

        // 继续接收下一个命令
        client.BeginReceive(OnReceive, null);
    }

    void SwitchScene()
    {
        // 切换到另一个场景
        SceneManager.LoadScene("AnotherScene");
    }

    void CreateObject()
    {
        // 创建一个简单的游戏物体
        GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.transform.position = new Vector3(0, 1, 0);
    }

    void OnDestroy()
    {
        client.Close();
    }
}

此脚本在 Unity 中启动时会向 QT 服务器发送一条消息。QT收到消息后会获取Unity程序的窗口句柄,并把这个窗口嵌入到QT中

实际应用场景

通过上述设置,QT 程序可以在桌面上实时控制 VR 场景中的行为,例如切换场景或创建游戏物体。这种交互方式适用于各种需要实时控制 VR 场景的应用场景,比如 VR 培训、虚拟展览等。

总结

本文详细介绍了如何通过 QT 服务器向 Unity VR 程序发送命令,以实现场景切换和游戏物体创建等交互功能。通过 UDP 进行通讯,您可以实现桌面和 VR 头盔之间的无缝互动,提升用户体验。如果您在实施过程中遇到问题或有其他需求,欢迎交流讨论。

标签:exe,QT,void,Unity,client,QString,data
From: https://blog.csdn.net/fuchenyang01/article/details/141719776

相关文章

  • 【Unity踩坑记录】使用Rigidbody模拟跳跃时,刚体会突然上升
    最初的写法privatevoidFixedUpdate(){if(!isGrounded){return;}floatrawHorizontal=Input.GetAxis("Horizontal");floatrawVertical=Input.GetAxis("Vertical");Vector3localDirection=new(rawHorizon......
  • 四博智联OpenMQTTGateway蓝牙网关,支持100多种蓝牙传感器
    以下是一篇关于OpenMQTTGateway的软文,包含了相关图片,以更好地展示该项目的功能和优势。模组规格OpenMQTTGateway:一站式解决物联网协议整合的强大工具OpenMQTTGateway是一个开源项目,旨在将多种不同的物联网协议整合到一个统一的固件中。通过这一创新性的解决方案,开发......
  • Qt | Qt是C++最好的图形界面开发库(学习路线图)
    点击上方"蓝字"关注我们01、WhatisQt?>>>Qt是一个跨平台的C++图形用户界面库,目前包括QtCreator、QtDesigner等等快速开发工具。Qt支持所有Linux/Unix系统,还支持windows平台。Qt很容易扩展,并且允许真正地组件编程。Qt与GTK、MFC、OWL、ATL 是一样的图形界......
  • MQTT详细介绍
    1.MQTT是什么  MQTT是基于发布与订阅模式的轻量级通讯协议,是基于TCP/IP建立的应用层协议。2.MQTT的特点轻量级:MQTT协议非常简洁,以极少的代码和有限的带宽就能实现可靠的消息传输。实时性:MQTT提供实时消息服务,确保设备之间的数据传输及时可靠。低开销:MQTT协议的开销......
  • python打包exe文件注意事项
    1.进入虚拟环境一开始使用pipenvshell,后续可以使用conda。使用虚拟环境可以尽量减小软件包的大小,减少不相关包的引入。2.当前环境目录中不要有__init__.py因为,打包时很可能被当为环境,不再打包其他文件。3.制作main.spec安装pyinstaller包,配置你的exe的icon。pipinstal......
  • Android 开发兼容性问题,TaskExecutionException等问题。
    1、问题描述:kapt'com.github.bumptech.glide:compiler:4.12.0'org.gradle.api.tasks.TaskExecutionException:Executionfailedfortask':app:kaptJlbDebugKotlin'.2、问题分析: 如果多人协作开发,从仓库clone\下载的项目代码,就说明其他开发人员使用这套代码是可以......
  • QT在控件graphicsView中绘制箭头
    这里写自定义目录标题前言:基础夯实:成功效果展示:失败效果展示:核心代码:前言:对之前箭头没有成功绘制的补充,因为没有直接的箭头项,所以需要自己进行绘制基础夯实:可以直接看,建议看一下之前的绘制过程在控件graphicsView中实现绘图功能(一)在控件graphicsView中实现绘图功......
  • Windows exe程序静默安装、不提示
    前言全局说明Windowsexe程序静默安装、不提示一、说明环境:Windows11家庭版23H222631.3737二、exe安装包参数2.1静默安装/S(大写S)MuMuNG-setup-V4.0.2.3233-0808023553.exe/S2.2文件名:三、3.1文件名:3.2文件名:四、4.1文件名:4.2文件......
  • CMake构建学习笔记10-OsgQt库的构建
    笔者使用的OsgQt库是Github上openscenegraph仓库中托管的项目(地址),该库的功能是将Osg嵌入到Qt窗体中。不过该库的使用总是有点问题,具体的介绍笔者在之前的两篇博文中论述过:OSG嵌入QT的简明总结OSG嵌入QT的简明总结2因此,这里笔者还是将这个库分成了两个版本进行构建。构建topic/Q......
  • WPF 现代化开发教程:使用 Microsoft.Extensions.Hosting 和 CommunityToolkit.Mvvm
    介绍随着WPF应用程序的复杂性增加,使用现代化的开发工具和模式变得尤为重要。本教程将指导你如何使用Microsoft.Extensions.Hosting和CommunityToolkit.Mvvm来开发一个现代化的WPF应用程序。这些工具为开发者提供了依赖注入、应用程序生命周期管理、MVVM模式支持等功能。先决......