unity python服务器_Unity如何连接服务器: 一个简单的例子

article/2025/10/22 20:36:51

Unity3D本身是用来做客户端的通用游戏引擎, 要建立网络连接的话, 其实需要使用的是C#本身的网络和线程模块, 即System.Net.Sockets & System.Threading. 本文中我做了一个简单的例子, 适合那些需要做Unity客户端连接服务器功能的人入门.

整体项目

客户端: 我做的项目主要是一个简单的Demo, 画面上只有三个按钮和两个输入框, 通过点击按钮可以实现相应的操作.

服务端: 服务端是一个Python写的服务器. 这个部分不是我本文的重点, 大家可以参考别的网上文章, 了解如何写一个C++, Python或者Java服务器, 无论什么语言写的服务器都是可以与Unity进行交互的.

a591f85dbcd4

Unity Network Demo

a591f85dbcd4

login点击后, console上显示了发出的消息

a591f85dbcd4

server显示成功登陆

下载项目后, 使用Unity导入, 可以看到Scripts文件夹中有六个脚本, 其中NetworkCore和UIManager是主要的脚本, Json开头的脚本不是重点, 他们只是Json编码解码相关的一个库(文中我是直接使用的https://github.com/gering/Tiny-JSON这个老外写的纯C#版本Json Parser), Json的编码和解析也不是本文重点, 只要找到一个库能用即可.

后续补充: Json的工具库现在推荐使用Newtonsoft出品的json.NET. 下载地址https://github.com/JamesNK/Newtonsoft.Json/releases, 在Unity2018.1中, 请使用其中的Bin\net20\Newtonsoft.Json.dll这个大小513KB的DLL(此处我也在微云存了一个供大家快速下载https://share.weiyun.com/5pky2k3), 由于Unity2018用的还是.NET2.0版本, 因此要用老的.

a591f85dbcd4

脚本一览

学习步骤

下载客户端和服务端, 运行起来. 之后主要学习NetworkCore.cs和UIManager.cs这两个脚本的内容(两个脚本并不复杂), 最关键的部分是如何建立连接, 建立后台线程, 发送和接收数据, 以及Json相关的字典操作.

脚本1: NetworkCore.cs

using System;

using System.Collections.Generic;

using System.Net.Sockets;

using System.Text;

using System.Threading;

using UnityEngine;

using Tiny;

public class NetworkCore : MonoBehaviour {

public string serverAddress = "127.0.0.1";

public int serverPort = 5000;

public string username = "chen";

public string password = "123";

private TcpClient _client;

private NetworkStream _stream; // C#中采用NetworkStream的方式, 可以类比于python网络编程中的socket

private Thread _thread;

private byte[] _buffer = new byte[1024]; // 接收消息的buffer

private string receiveMsg = "";

private bool isConnected = false;

void Start() {

}

public void OnApplicationQuit() {

Dictionary dict = new Dictionary()

{

{"code", "exit"}

};

SendData(Encode(dict)); // 退出的时候先发一个退出的信号给服务器, 使得连接被正确关闭

Debug.Log("exit sent!");

CloseConnection ();

}

// --------------------public--------------------

public void Login() {

SetupConnection();

Dictionary dict = new Dictionary()

{

{"code", "login"},

{"username", username},

{"password", password}

};

SendData(Encode(dict));

Debug.Log("start!");

}

public void SendGameData(int score, int health) {

Dictionary dict = new Dictionary()

{

{"code", "gds"},

{"score", score.ToString()},

{"health", health.ToString()}

};

SendData(Encode(dict));

}

// -----------------------private---------------------

private void SetupConnection() {

try {

_thread = new Thread(ReceiveData); // 传入函数ReceiveData作为thread的任务

_thread.IsBackground = true;

_client = new TcpClient(serverAddress, serverPort);

_stream = _client.GetStream();

_thread.Start(); // background thread starts working while loop

isConnected = true;

} catch (Exception e) {

Debug.Log (e.ToString());

CloseConnection ();

}

}

private void ReceiveData() { // 这个函数被后台线程执行, 不断地在while循环中跑着

Debug.Log ("Entered ReceiveData function...");

if (!isConnected) // stop the thread

return;

int numberOfBytesRead = 0;

while (isConnected && _stream.CanRead) {

try {

numberOfBytesRead = _stream.Read(_buffer, 0, _buffer.Length);

receiveMsg = Encoding.ASCII.GetString(_buffer, 0, numberOfBytesRead);

_stream.Flush();

Debug.Log(receiveMsg);

receiveMsg = "";

} catch (Exception e) {

Debug.Log (e.ToString ());

CloseConnection ();

}

}

}

private void SendData(String msgToSend)

{

byte[] bytesToSend = Encoding.ASCII.GetBytes(msgToSend);

if (_stream.CanWrite)

{

_stream.Write(bytesToSend, 0, bytesToSend.Length);

}

}

private void CloseConnection() {

if (isConnected) {

_thread.Interrupt (); // 这个其实是多余的, 因为isConnected = false后, 线程while条件为假自动停止

_stream.Close ();

_client.Close ();

isConnected = false;

receiveMsg = "";

}

}

// ---------------------util----------------------

// encode dict to to json and wrap it with \r\n as delimiter

string Encode(Dictionary dict)

{

string json = Json.Encode(dict);

string header = "\r\n" + json.Length.ToString() + "\r\n";

string result = header + json;

Debug.Log("encode result:" + result);

return result;

}

// decode data, 注意要解决粘包的问题, 这个程序写法同GameLobby中的相应模块一模一样

// 参考 https://github.com/imcheney/GameLobby/blob/master/server/util.py

Dictionary Decode(string raw)

{

string payload_str = "";

string raw_leftover = raw;

if (raw.Substring(0, 2).Equals("\r\n"))

{

int index = raw.IndexOf("\r\n", 2);

int payload_length = int.Parse(raw.Substring(2, index - 2 + 1)); // 注意, C#'s substring takes start and length as args

if (raw.Length >= index + 2 + payload_length)

{

payload_str = raw.Substring(index + 2, payload_length);

raw_leftover = raw.Substring(index + 2 + payload_length);

}

}

return Json.Decode>(payload_str);

}

}

脚本2: UIManager.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI; //using 关键字用于在程序中包含命名空间。一个程序可以包含多个 using 语句。

public class UIManager : MonoBehaviour {

public InputField scoreInputField;

public InputField healthInputField;

NetworkCore networkCore;

// Use this for initialization

void Start () {

networkCore = GetComponent();

}

// Update is called once per frame

void Update () {

}

public void OnLoginButton() {

networkCore.Login();

}

public void OnSendButton() {

int score = int.Parse(scoreInputField.text);

int health = int.Parse(healthInputField.text);

networkCore.SendGameData(score, health);

}

public void OnQuitButton()

{

int score = int.Parse(scoreInputField.text);

int health = int.Parse(healthInputField.text);

networkCore.SendGameData(score, health);

Application.Quit();

}

}

后续持续开发优化建议


http://chatgpt.dhexx.cn/article/hogBQvCm.shtml

相关文章

unity + python socket通信,自定义数据包

unity和python相互之间通过socket通信来发送自定义数据包是一个利用unity构建场景和通过python来做数据处理的方式,能够有效的利用两种不同语言的优势。 我已经将对应的操作封装为对应的一个模块,SocketTools.cs,我们先来看一下具体的代码用…

假设电话收费标准为: (1)国际长途1.00元/分钟,(2) 国内长途0.60元/分钟,(3)市话前3分钟0.20元,3分钟以后0.10元/分钟。现假设某话单文件中每条话单包含如下信息:通话日期(10

你好,帮我做个C语言题目 你好,我是Assistant。很高兴为您做题。 请提供题目的完整题面,并提供任何相关的输入、输出、约束条件等信息。 如果您有任何其他问题,请随时与我联系。我将竭诚为您服务。 897354667qq.com 假设电话收…

电商用户行为数据分析实战(MySQL +PowerBI)

目录 一、项目概况二、数据源三、数据清洗3.1 选择子集导入,匹配适合的数据类型3.2 列重命名3.3重复值处理3.4 缺失值处理3.5 异常值处理从timestamps字段中提取日期数据列查看日期列数据异常情况 四、数据分析4.1 整体购物情况,基于AARRR模型4.1.1 各字…

【业务数据分析】——十大常用数据分析方法

🤵‍♂️ 个人主页:Lingxw_w的个人主页 ✍🏻作者简介:计算机科学与技术研究生在读 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 &#x1f4a…

基于订单的数据分析

目录 项目背景 数据理解 指标维度 指标梳理 维度梳理 导入数据 数据预处理 数据格式整理 规范字段名 增加字段 简化地址 缺失值处理 异常值分析​ 重复值处理 数据分析 描述性统计 总体销售情况 周趋势、日趋势分析 产品价格分析 地区分析 转化率分析 总结…

大数据培训 | 电商用户行为分析之订单支付实时监控

在电商网站中,订单的支付作为直接与营销收入挂钩的一环,在业务流程中非常重要。对于订单而言,为了正确控制业务流程,也为了增加用户的支付意愿,网站一般会设置一个支付失效时间,超过一段时间不支付的订单就…

订单数据分析

订单背景 订单:对订单的预测不仅为了企业更好的制定物料采购计划、控制库存、提升生产效率、控制生产进度,还为了帮助企业更好的把控市场潜在需求,分析目前经营状态和未来发展趋势。 宽厚板材市场价格(只能查询到近三个月的&…

关于订单功能的处理和分析

这两天看了一下RABC的权限管理处理,梳理了一下订单功能的表创建,界面,功能分析。 目录 RABC RBAC0模型 那么对于RABC模型我们怎么创建数据库表? 订单模块的梳理 RABC RABC说的是在用户和权限之间多一个角色,用户与…

订单数据分析-实战

1. 京东订单数据准备 1.1 京东订单数据介绍 2020年5月25日10%抽样数据大家电-家用电器-冰箱70K 1.2 数据清洗 缺失值处理 用户城市和省份信息有部分缺失,部分订单的订单中支付时间为空值数据逻辑错误格式内容一致性 import pandas as pd import numpy as np im…

话单数据完整流程

原始数据__解析_____>>>解析后的数据___入库____>>>汇总的数据 1.原始数据 上游中兴的原始数据,在远程桌面Winscp软件中查看。丢失了下游也没法补充采集。得等上游补充采集后下游才能解析。当原始数据存在,而话单数据显示红点&…

话单分析账单分析行踪分析三合一数据分析

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

Office Tool Plus(安装visio)

说明:需要提前卸载原先的Office(Word、PPT、Excel等) 一、Office Tool Plus官网 https://otp.landian.vip/zh-cn/download.html 二、下载Office Tool Plus 百度网盘链接(Office Tool Plus安装包) 链接:…

FFmpeg音频解码-音频可视化

最近在做一个音频可视化的业务,网上有Java层的实现方法,但是业务需要用C实现,从原理出发其实很简单,先对音频进行解码,再计算分贝。这比把大象放进冰箱还简单。本文从音频可视化的业务为依托,以FFmpeg为基础…

基于FFmpeg的视频播放器之七:音频解码

一.流程 音频解码的流程和视频解码几乎一样,最大的区别是解码后需要进行重采样。因为解码出的AVSampleFormat格式是AV_SAMPLE_FMT_FLTP(float, planar),该格式无法直接使用SDL进行播放,需要转换成SDL支持的AV_SAMPLE_FMT_S16(signed 16 bits)格式。关于重采样,详见下篇…

2020手机音频解码芯片_2020杰理音频芯片全解析,14款音频产品代表作拆解汇总...

珠海市杰理科技股份有限公司,成立于2010年。杰理科技主要从事射频智能终端、多媒体智能终端等系统级芯片(SoC)的研究、开发和销售。 杰理科技的芯片产品主要应用于AI智能音箱、蓝牙音箱、蓝牙耳机、智能语音玩具等物联网智能终端产品,下游应用产品市场十分广泛和巨大。 杰理科…

音频编解码原理

实例说明 音频编解码常用的实现方案有三 种。 第一种就是采用专用的音频芯片对 语音信号进行采集和处理,音频编解码算法集成在硬件内部,如 MP3 编解码芯片、语音合成 分析芯片等。使用这种方案的优点就是处理速度块,设计周期短;缺…

基于STM32音频解码MP3——vs1053

基于正点原子教程 VS1053简介: 1.该模块采用VS1053B 作为主芯片 2.支持:MP3/WMA/OGG/WAV/FLAC/MIDI/AAC 等音频格式的解码 3.支持:OGG/WAV 音频格式的录音,支持高低音调节以及 EarSpeaker 空间效果设置 模块如图所示正点原子 AL…

ijkplayer音频解码播放架构分析

ijkplayer是一款跨平台播放器,支持Android与iOS播放,音频解码默认使用FFmpeg的avcodec软解。Android端播放音频可以用OpenSL ES和AudioTrack,而iOS端播放音频默认使用AudioQueue。 一、iOS音频解码播放 采用pipeline形式创建音频播放组件&a…

HIFI音频解码芯片ES9023

现在的HiFi播放器、解码耳放设备越来越多,推陈出新的速度也越来越快。各家厂商也都对产品进行了卖点细分,把新款旗舰级解码芯片拎出来宣传。美国ESS公司推出的ES9038Pro芯片大家都早已耳熟能详。 美国ESS系列芯片拥有行业高标准的信噪比 DNR(…

DP7398:国产兼容替代CS4398立体声24位/192kHz音频解码芯片

目录 DP7398简介结构框图芯片特性 应用领域 DP7398简介 DP7398是立体声 24 位/192kHz 数模转换芯片。该D/A系统包括数字去加重、半分贝步长音量控制、ATAPI 通道混频、可选择的快速和慢速数字插补滤波器和过采样多位增量 Sigma-Delta 调制器;该调制器采用失调整形技…