QT+Unity3D 超详细(将unity3D与QT进行连接,并实现信息传递)

news2024/11/27 20:57:36

QT+Unity3D连接

在QT中连接unity3D,首先要有一个unity.exe执行文件。在这里不提供unity执行文件的编写,只提供QT这边与unity3D连接和信息传递。

创建项目

创建一个新的项目,我创建的项目名称如下。
Alt
下图是我建立新项目的文件。APP文件就是我的unity.exe执行文件。
Alt
打开APP文件,里面就是关于unity3D的东西了。
Alt

直接上代码(看注释更通透)

unityConnect.pro文件中添加QT += network模块。

QT       += core gui
QT       += network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    UnityConfigure.cpp \
    main.cpp \
    UnityShow.cpp

HEADERS += \
    UnityConfigure.h \
    UnityShow.h

FORMS += \
    UnityShow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

UnityConfigure.h中。

#ifndef UNITYCONFIGURE_H
#define UNITYCONFIGURE_H

#include <QObject>
#include <QProcess>
#include <windows.h>
#include <winuser.h>
#include <qDebug>
class UnityConfigure : public QObject
{
    Q_OBJECT
public:
    explicit UnityConfigure(QObject *parent = nullptr);
    ~UnityConfigure();
    void startUnityProgram(const QString& unityExePath);

    void setWindowParent(HWND parentWidgetHandle, const QString& sonWindowTitleName);
    QProcess* process;
signals:
    void unityProgramStarted();
};

#endif // UNITYCONFIGURE_H

UnityConfigure.cpp中。

#include "UnityConfigure.h"

UnityConfigure::UnityConfigure(QObject *parent)
    : QObject{parent}
{
    process = new QProcess(this);//创建一个新的进程
    connect(process, &QProcess::started, this, &UnityConfigure::unityProgramStarted);//将进程与unity连接起来
}
UnityConfigure::~UnityConfigure()//用于关闭
{
    process->kill();//关闭进程
}
void UnityConfigure::startUnityProgram(const QString& unityExePath)
{
    process->setProgram(unityExePath);//设置unity路径
    process->start(QIODevice::Truncate);//启动进程
}

void UnityConfigure::setWindowParent(HWND parentWidgetHandle, const QString& sonWindowTitleName)//设置unity窗口属性
{
    std::wstring titleName = sonWindowTitleName.toStdWString();//设置unity标题
    HWND hfigure = nullptr;
    while (true)
    {
        hfigure = FindWindowW(nullptr, titleName.c_str());
        if (hfigure != nullptr)
        {
            break;
        }
    }
    RECT rect;
    GetWindowRect(parentWidgetHandle, &rect);//得到你要嵌入QT控件窗口的大小
    SetParent(hfigure, parentWidgetHandle);//将unity嵌入到QT控件中

    LONG_PTR dwStyle = GetWindowLongPtr(hfigure, GWL_STYLE);//子窗口样式
    dwStyle = dwStyle & ~(WS_THICKFRAME | WS_CAPTION | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);//移除子窗口的移动和调整大小的样式
    //如果想要使用unity缩放功能,就需要把"dwStyle |= WS_CHILD | WS_CLIPCHILDREN;"这行注释掉就可以了
    dwStyle |= WS_CHILD | WS_CLIPCHILDREN;//添加固定位置的样式。WS_CHILD 表示这是一个子窗口,WS_CLIPCHILDREN 表示绘制子窗口时,只绘制子窗口区域内的内容。
    SetWindowLongPtr(hfigure, GWL_STYLE, dwStyle);//更新子窗口的样式

    //这段代码用于改变unity窗口在QT控件中的位置以及大小。
//    MoveWindow(hfigure, 0, 0, 1400, 870, false);
//    SetWindowPos(hfigure, HWND_TOP, 0, 0, 1400, 870, SWP_SHOWWINDOW |SWP_HIDEWINDOW);
//    ShowWindow(hfigure, SW_SHOW);
//    SetFocus(hfigure);
}

UnityShow.h中。

#ifndef UNITYSHOW_H
#define UNITYSHOW_H

#include <QMainWindow>
#include "UnityConfigure.h"
#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class UnityShow; }
QT_END_NAMESPACE

class UnityShow : public QMainWindow
{
    Q_OBJECT
    UnityConfigure* unity;
    QTcpSocket* tcpSocket;
public:
    UnityShow(QWidget *parent = nullptr);
    ~UnityShow();
    void onReceive();//接收数据
    void onSend();//发送数据
private slots:
    void onConnected();//连接建立时的处理
    void onDisconnected();//连接断开时的处理
private:
    Ui::UnityShow *ui;
};
#endif // UNITYSHOW_H

UnityShow.cpp中。

#include "UnityShow.h"
#include "ui_UnityShow.h"

UnityShow::UnityShow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::UnityShow)
{
    ui->setupUi(this);
    unity = new UnityConfigure(this);
    QString titleName("1025using");//创建标题,切记要与unity执行文件名字相同,要不然无法嵌入到QT中

    QString unityExePath("./APP/1025using.exe");//读取unity路径
    //将QT与unity进行连接
    connect(unity, &UnityConfigure::unityProgramStarted, this, [&]()
            {
                unity->setWindowParent((HWND)ui->unityWidget->winId(),titleName);
            });
    unity->startUnityProgram(unityExePath);//启动unity
    tcpSocket = new QTcpSocket(this);//创建TCP通信
    tcpSocket->connectToHost("127.0.0.1", 9999);//进行和unity接口连接,这个接口是在unity里面进行设置的,QT直接用就行。
    connect(tcpSocket, &QTcpSocket::connected, this, &UnityShow::onConnected);
    connect(tcpSocket, &QTcpSocket::disconnected, this, &UnityShow::onDisconnected);
    onSend();//进行发送消息
}

UnityShow::~UnityShow()
{
    delete ui;
}

void UnityShow::onConnected()
{
    // 连接建立时的处理
    qDebug()<<"Connected successfully!";
}

void UnityShow::onDisconnected()
{
    // 连接断开时的处理
    qDebug()<<"disConnected successfully!";
}

void UnityShow::onReceive()
{
    // 接收unity发送的命令,收到命令之后去执行QT这边的操作。
    QByteArray data = tcpSocket->readAll();
}
void UnityShow::onSend()
{
    /*
     * 发送信息,BulletEyeRendezvous这条信息是在unity中进行设置的,
     * 然后在QT中进行发送这条消息即可。发完之后unity会执行这条信息,
     * 去执行unity接下来的程序。
    */
    QString msg="BulletEyeRendezvous";//unity设置的命令
    tcpSocket->write(msg.toUtf8());//进行发送命令
}

UnityShow.ui中,定义一个Widget控件即可。
Alt

运行结果

Alt

如果不想出现下面的unity边框,就在UnityConfigure.cpp中加上这行代码dwStyle |= WS_CHILD | WS_CLIPCHILDREN; 加完之后就不能使用unity缩放功能。
如果想要使用unity缩放功能,就需要把dwStyle |= WS_CHILD | WS_CLIPCHILDREN; 这行注释掉就可以了,但会出现unity边框。
目前我还没找到两全其美的办法,如果哪位大佬有更好的解决方法,欢迎您在评论区留言。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1291403.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring boot 使用Redis 消息发布订阅

Spring boot 使用Redis 消息发布订阅 文章目录 Spring boot 使用Redis 消息发布订阅Redis 消息发布订阅Redis 发布订阅 命令 Spring boot 实现消息发布订阅发布消息消息监听主题订阅 Spring boot 监听 Key 过期事件消息监听主题订阅 最近在做请求风控的时候&#xff0c;在网上搜…

智能成绩表 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 100分 题目描述 小明来到某学校当老师,需要将学生按考试总分或单科分数进行排名,你能帮帮他吗? 输入描述 第1行输入两个整数,学生人数n和科目数量m。0<n<100,0<m<10 第2行输入m个科目名称,彼此之间用空格隔开。科目名称只由英文…

备战2024年1月AMC8美国数学竞赛新方式:刷在线真题集(附资源)

今天是2023年12月7日&#xff0c;距离暂定于2024年1月19日举办的AMC8美国数学竞赛的举办日期还有42天&#xff0c;有志于尽早出国留学&#xff0c;或者小升初冲击名校的孩子们相信已经在如火如荼地利用课余时间上辅导班或者自学。 为了帮助大家提高备考2024年1月份AMC8竞赛的效…

二百一十、Hive——Flume采集的JSON数据文件写入Hive的ODS层表后字段的数据残缺

一、目的 在用Flume把Kafka的数据采集写入Hive的ODS层表的HDFS文件路径后&#xff0c;发现HDFS文件中没问题&#xff0c;但是ODS层表中字段的数据却有问题&#xff0c;字段中的JSON数据不全 二、Hive处理JSON数据方式 &#xff08;一&#xff09;将Flume采集Kafka的JSON数据…

设计一算法,对单链表实现就地逆置

对单链表逆置&#xff0c;要联想到单链表的头插性质 举个例子&#xff1a;现在有一个空链表&#xff0c;我们依次对它进行头插123 那么形成的链表是321&#xff0c;这样就形成了逆置 //单链表就地逆置 //思路&#xff1a;把原表接到一个新表上&#xff0c;然后对原表进行头插 …

实例分割 Mask-RCNN

参考文章 使用LabelMe标注目标检测数据集并转换为COCO2017格式_labelme转coco-CSDN博客 数据集选择 voc 这次不选择voc&#xff0c;因为文件组织太难了 voc2012文件夹组织 COCO COCO介绍 MC COCO2017年主要包含以下四个任务&#xff1a;目标检测与分割、图像描述、人体关…

【论文阅读】Bayes’ Rays:神经辐射场的不确定性量化

【论文阅读】Bayes’ Rays&#xff1a;神经辐射场的不确定性量化 1. Introduction2. Related work3. Background3.2. Neural Laplace Approximations 4. Method4.1. Intuition4.2. Modeling perturbations4.3. Approximating H4.4. Spatial uncertainty 5. Experiments & A…

多域名SSL证书该怎么分类

多域名SSL证书多域名SSL证书是一种网络安全工具&#xff0c;它能够为多个域名提供加密和安全保障。多域名SSL证书可以同时保护多个不同的域名站点&#xff0c;为用户打造安全可靠的网络环境。今天就随SSL盾小编了解多域名SSL证书的分类。 1.多域名SSL证书按照验证方式分为DV基础…

Java项目学生管理系统六后端补充

班级管理 1 班级列表&#xff1a;后端 编写JavaBean【已有】编写Mapper【已有】编写Service编写controller 编写Service 接口 package com.czxy.service;import com.czxy.domain.Classes;import java.util.List;/*** author 桐叔* email liangtongitcast.cn* description*/ p…

老师可以做副业吗

当老师&#xff0c;除了教学工作之外&#xff0c;还可以怎样来丰富自己的职业体验和增加收入呢&#xff1f; 自媒体作者 许多教师选择成为自媒体作者&#xff0c;分享自己的教育心得、教学经验以及与学生相处的生活状态等。通过撰写文章、发布在社交媒体上&#xff0c;不仅可以…

单片机第三季-第六课:STM32标准库

1&#xff0c;为什么会有标准外设库 传统单片机软件开发方式&#xff1a; (1)芯片厂商提供数据手册、示例代码、开发环境&#xff1b; (2)单片机软件工程师面向产品功能&#xff0c;查阅数据手册&#xff0c;参考官方示例代码进行开发&#xff1b; (3)硬件操作的方式是用C语言…

大屏图表汇总echarts圆环

圆环效果示例 代码如下 storageStaChart() {let color [#009976,#15E6B5]let charts echarts.init(document.getElementById(storageStaChart));let option this.getPieOption(color);charts.setOption(option, true);}, getPieOption(color) {let data [];data.push({val…

2023年7月13日 Go生态洞察:Govulncheck v1.0.0的全面解析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

学习mysql记录

环境: macbookpro m1 1. 安装mysql 使用苹果自带的包管理工具brew进行安装 1. brew install mysql (安装) 2. brew services start mysql (启动mysql服务) 1.1 如果提示zsh: mysql command not found, 终端执行以下命令 1. cd ~ (切到根目录) 2. vi .bash_profile (进入编辑…

从零开始,利用ChatGPT学会写作的完整指南

文章目录 前言了解ChatGPT访问OpenAI平台使用ChatGPT进行简单的对话定义写作主题逐步生成文章段落添加个性化和细节编辑和润色反复修改直至满意 图书推荐内容简介作者简介获取方式 前言 在数字时代&#xff0c;人工智能技术日益成熟&#xff0c;为我们提供了全新的学习和创作机…

【Linux】在磁盘中如何找到文件 -- 磁盘的物理结构与逻辑结构

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法…感兴趣就关注我吧&#xff01;你定不会失望。 本篇导航 0. 磁盘物理结构介绍1. 磁盘逻辑结构2. 文件系统划分3. 如何理解文件目录4. 对文件的增删查改5. 软链接与硬链接5.1 软链接5.2.…

【C++11(二)】lambda表达式以及function包装器

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; C11 1. 前言2. lambda表达式的提出3. lambda表达…

mixamo根动画导入UE5问题:滑铲

最近想做一个跑酷游戏&#xff0c;从mixamo下载滑铲动作后&#xff0c;出了很多动画的问题。花了两周时间&#xff0c;终于是把所有的问题基本上都解决了。 常见问题&#xff1a; 1.【动画序列】人物不移动。 2.【动画序列】人物移动朝向错误。 3.【蒙太奇】人物移动后会被拉回…

c语言五子棋

下面是一个简单的C语言五子棋实现示例&#xff1a; #include <stdio.h>#include <stdlib.h>#define BOARD_SIZE 15char board[BOARD_SIZE][BOARD_SIZE];void init_board() { int i, j; for (i 0; i < BOARD_SIZE; i) { for (j 0; j < BOARD_…

AIGC:使用变分自编码器VAE实现MINIST手写数字生成

1 变分自编码器介绍 变分自编码器&#xff08;Variational Autoencoders&#xff0c;VAE&#xff09;是一种生成模型&#xff0c;用于学习数据的分布并生成与输入数据相似的新样本。它是一种自编码器&#xff08;Autoencoder&#xff09;的扩展&#xff0c;自编码器是一种用于…