unity开发:Qt C++与unity之间TCP网络通信

考虑实现用C++做服务器,unity做客户端实现TCP网络通信。

以下采用TCP单线程连接。

Qt C++服务端

建立一个Qt的GUI项目,在界面上放一个label显示连接状态,两个button作为指令发送控制。

记得在pro文件中加入network模块

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class QTcpServer;//前向声明
class QTcpSocket;

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;

private:
    QString statusText; //状态信息
    QTcpServer *tcpServer; //服务器
    QTcpSocket *clientTcpSocket; //客户端socket
    void SocketSend(QString sendStr);
private slots:
    void SocketConnet();
    void SocketReceive();
    void on_leftBtn_clicked();
    void on_rightBtn_clicked();
};

#endif // WIDGET_H

widget.cpp

#include <QTcpServer>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QDebug>
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //初始化server并监听
    tcpServer=new QTcpServer(this); //qt自己内存管理
    if(!tcpServer->listen(QHostAddress::Any,6666)) //监听所有网络地址,端口6666
        qDebug()<<tcpServer->errorString();
    statusText=statusText+"wait for connecting..."+"\n";
    ui->statusLabel->setText(statusText);
    //绑定信号槽,当有连接时作出反应
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(SocketConnet()));
}

void Widget::SocketConnet()
{
    //获得client socket
    clientTcpSocket=tcpServer->nextPendingConnection();
    //绑定信号槽,接收数据,并且当连接关闭是删除连接
    connect(clientTcpSocket,SIGNAL(readyRead()),this,SLOT(SocketReceive()));
    connect(clientTcpSocket,SIGNAL(disconnected()),clientTcpSocket,SLOT(deleteLater()));
    //显示客户端连接信息
    QString clientIp=clientTcpSocket->peerAddress().toString();
    QString clientPort=QString::number(clientTcpSocket->peerPort());
    statusText=statusText+"conneted with "+clientIp+":"+clientPort+"\n";
    ui->statusLabel->setText(statusText);
}

void Widget::SocketSend(QString sendStr)
{
    clientTcpSocket->write(sendStr.toStdString().c_str());
}

void Widget::SocketReceive()
{
    //接收数据并显示,字节转换成了字符串
    QString recvStr=clientTcpSocket->readAll();
    statusText=statusText+recvStr+"\n";
    ui->statusLabel->setText(statusText);
    //经处理后发送回去
    SocketSend("From server: "+recvStr);
}

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

//发送unity物体左旋消息
void Widget::on_leftBtn_clicked()
{
    SocketSend("leftrotate");
}

//发送unity物体右旋消息
void Widget::on_rightBtn_clicked()
{
    SocketSend("rightrotate");
}

main.cpp未更改就不贴了。

unity C#客户端

建立一个unity场景,拖入一个cube

把tcpsocket连接部分封装成了一个单独的类TcpClientHandler,再加一个脚本TcpTest挂到场景中,在这个脚本中实例化用于连接的TcpClientHandler。

TcpClientHandler.cs

using UnityEngine;
using System.Collections;
//引入库
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TcpClientHandler:MonoBehaviour
{
    Socket serverSocket; //服务器端socket
    IPAddress ip; //主机ip
    IPEndPoint ipEnd;
    string recvStr; //接收的字符串
    string sendStr; //发送的字符串
    byte[] recvData=new byte[1024]; //接收的数据,必须为字节
    byte[] sendData=new byte[1024]; //发送的数据,必须为字节
    int recvLen; //接收的数据长度
    Thread connectThread; //连接线程

    //初始化
    public void InitSocket()
    {
        //定义服务器的IP和端口,端口与服务器对应
        ip=IPAddress.Parse("127.0.0.1"); //可以是局域网或互联网ip,此处是本机
        ipEnd=new IPEndPoint(ip,6666); //服务器端口号

        //开启一个线程连接,必须的,否则主线程卡死
        connectThread=new Thread(new ThreadStart(SocketReceive));
        connectThread.Start();
    }

    void SocketConnet()
    {
        if(serverSocket!=null)
            serverSocket.Close();
        //定义套接字类型,必须在子线程中定义
        serverSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        print("ready to connect");
        //连接
        serverSocket.Connect(ipEnd);

        //输出初次连接收到的字符串
        recvLen=serverSocket.Receive(recvData);
        recvStr=Encoding.ASCII.GetString(recvData,0,recvLen);
        print(recvStr);
    }

    public void SocketSend(string sendStr)
    {
        //清空发送缓存
        sendData=new byte[1024];
        //数据类型转换
        sendData=Encoding.ASCII.GetBytes(sendStr);
        //发送
        serverSocket.Send(sendData,sendData.Length,SocketFlags.None);
    }

    void SocketReceive()
    {
        SocketConnet();
        //不断接收服务器发来的数据
        while(true)
        {
            recvData=new byte[1024];
            recvLen=serverSocket.Receive(recvData);
            if(recvLen==0)
            {
                SocketConnet();
                continue;
            }
            recvStr=Encoding.ASCII.GetString(recvData,0,recvLen);
            print(recvStr);
        }
    }

    //返回接收到的字符串
    public string GetRecvStr()
    {
        string returnStr;
        //加锁防止字符串被改
        lock(this)
        {
            returnStr=recvStr;
        }
        return returnStr;
    }
    public void SocketQuit()
    {
        //关闭线程
        if(connectThread!=null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
        //最后关闭服务器
        if(serverSocket!=null)
            serverSocket.Close();
        print("diconnect");
    }

}

TcpTest.cs

using UnityEngine;
using System.Collections;

public class TcpTest:MonoBehaviour
{
    string editString="hello wolrd"; //编辑框文字
    GameObject cube;

    TcpClientHandler tcpClient;
    // Use this for initialization
    void Start()
    {
        //初始化网络连接
        //tcpClient=new TcpClientHandler(); //因为tcp的类继承了monobehaviour所以不能用new,或者去掉对monobehaviour继承就可以用new
        tcpClient=gameObject.AddComponent<TcpClientHandler>();
        tcpClient.InitSocket();

        //找到cube
        cube=GameObject.Find("Cube");
    }

    void OnGUI()
    {
        editString=GUI.TextField(new Rect(10,10,100,20),editString);
        GUI.Label(new Rect(10,30,300,20),tcpClient.GetRecvStr());
        if(GUI.Button(new Rect(10,50,60,20),"send"))
            tcpClient.SocketSend(editString);
    }

    // Update is called once per frame
    void Update()
    {
        if(tcpClient.GetRecvStr()!=null)
        {
            switch(tcpClient.GetRecvStr())
            {
                case "leftrotate":
                    cube.transform.Rotate(Vector3.up,50*Time.deltaTime);
                    break;
                case "rightrotate":
                    cube.transform.Rotate(Vector3.down,50*Time.deltaTime);
                    break;
            }
        }
    }

    void OnApplicationQuit()
    {
        //退出时关闭连接
        tcpClient.SocketQuit();
    }
}

测试

程序实现服务端和客户端互相收发消息,服务端按钮可以控制客户端里面的cube旋转。

时间: 2024-11-03 05:28:11

unity开发:Qt C++与unity之间TCP网络通信的相关文章

【Unity】第6章 Unity脚本开发基础

分类:Unity.C#.VS2015 创建日期:2016-04-16 一.简介 游戏吸引人的地方在于它的可交互性.如果游戏没有交互,场景做得再美观和精致,也难以称其为游戏. 在Unity中,游戏交互通过脚本编程来实现.脚本可以理解为附加在游戏对象上的用于定义游戏对象行为的指令代码.通过脚本,开发者可以控制每一个游戏对象的创建.销毁以及对象在各种情况下的行为,进而实现预期的交互效果. 在Unity中进行脚本开发十分简易和高效,这是因为Unity的编辑器整合了很多脚本编辑的功能,比如脚本与游戏对象的

unity 开发入门

---恢复内容开始--- 使用Unity开发一个打飞机的初级入门小游戏. 实现功能: 一.界面UI:3个界面:1开始界面,2游戏界面,3解释界面. 1.开始界面: 主要代码: using UnityEngine;using System.Collections; public class projectile : MonoBehaviour { private Transform m_projectile; private Rigidbody goprojectile; void Start (

Unity 5实战 使用C#和Unity开发多平台游戏pdf

下载地址:城通网盘 作者简介 编辑 Joseph Hocking是一位交互式媒体开发方面的软件工程师.他就职于Synapse Games公司并在芝加哥哥伦比亚学院教授游戏开发课程.[1] " src="/CuteSoft_Client/CuteEditor/Images/anchor.gif"> 目 录 编辑 " src="/CuteSoft_Client/CuteEditor/Images/anchor.gif"> 第Ⅰ部分 起 步

蓝鸥Unity开发基础——If 语句学习笔记

蓝鸥Unity开发基础--If 语句学习笔记 本节内容:程序的三种结构,if语句,问号表达式 程序的三种结构 顺序结构:顺序执行语句 分支结构:通过进行判断,在多个语句块中选择某一个执行 循环结构:条件满足时,反复执行同一语句块 If语句 用if语句可以构成分支结构 它根据给定的条件进行判定,用来决定要执行某个程序段 一.if(条件表达式){语句1} using System; namespace Lesson11{    class MainClass    {        public s

Unity多玩家网络游戏开发教程1章Unity带有网络功能

Unity网络多玩家游戏开发教程第1章Unity自带网络功能 Unity拥有大量的第三方插件.专门提供了对网络功能的支持. 可是.大部分开发人员第一次接触到的还是Unity自带的网络功能.也就是大家常常说到的Unity Networking API.这些API是借助于组件NetworkView发挥作用的,而它能够简化开发人员大量的网络功能编码任务.本文选自<Unity网络多玩家游戏开发教程(大学霸内部资料)> NetworkView组件 在Unity中,NetworkView组件用于处理游戏在

HoloLens开发手记 - Unity development overview 使用Unity开发概述

Unity Technical Preview for HoloLens最新发行版为:Beta 24,发布于 09/07/2016 开始使用Unity开发HoloLens应用之前,确保你已经安装好了必要的工具,包括Unity HoloLens Technical Preview.Unity HoloLens Technical Preview是基于Unity 5.4 Beta版本来构建的,记得定期检查版本更新. 使用Unity是构建HoloLens全息应用最快的方式.推荐你花点时间来学习Unit

2017年Unity开发环境与插件配置安装(总体介绍)

最近(2017年初)有朋友问,Unity客户端开发如何在机器配置一般的情况下,配置更高效的开发环境,进一步加快开发进度. 推荐如下: Win10(或者Win8)+Unity5.5.1版本(2017年2月最新)+VS2012(或者VS2015) +UnityVS(支持Unity5.x版本)插件+Resharp8.0插件. 解释如下: 1: 操作系统推荐Win10或者Win8系统. 目前Unity5.0  以上版本都支持64位系统,带来更高的性能体验,所以不是太老的机器,一定用64位的Win操作系统

Leap Motion 之Unity 开发指南(一. 基本概念与制作手预制件)

LeapMotion 之Unity开发指南(一.基本概念和手的预制件) [序言] 最近用Leap Motion + 国产的3Glass眼镜构建了房地产.数字矿山的一些应用,感觉这是很经济的一个VR架构方案,比用Oculus和HTC的硬件要省钱得多,并且效果也不错. 在行业VR应用中,其实重在培训教育.生产安全的仿真演练上,更多地通过一些UI互动.基础性的手势(比如开关设备.拾起灭火装备等)来进行交互,这些并不一定需要非常昂贵的激光定位设备.复杂的硬件套件才可实现,而手势识别在未来也是一个趋势.

Unity 开发心得(1)

C#与JS用于unity开发的区别: C#中定义函数必须声明函数类型(void等),但是JS中可以未知函数类型直接定义(function) 注意 C#脚本在Rect前有个new JS脚本没有. 例:在unity中创建GUI控件 在unity中使用脚本都需要绑定游戏对象.例如GUI需要绑定在camera对象中才能在Game界面中显示出来.具体的操作是,选中游戏对象(例如camera),点击右边Inspector中的"Add Component"并选择需要绑定的脚本. C#脚本: void