Unity3d C#实现基于SocketIOUnity的与后端(node.js为例)Socket通信功能(含工程)

前言

该功能主要是项目上的需求,按后端的需求就是我们通过SocketIO进行通信,之前游戏通信功能大多是基于原始的Socket进行封装,需要对包体进行设计,还需要粘包拆包等系列操作,属实有点麻烦。这次尝试了SocketIOUnity的使用,感觉还是挺快速的就是实现了,而且也比较方便,所以将基本过程进行了总结分享。

效果

在这里插入图片描述
在这里插入图片描述

开源库

这个功能的实现主要基于GitHub上itisnajim封装的SocketIOUnity插件 ,而该插件是一个将socket.io-client-csharp与Unity一起工作的包装器, 支持 socket.io 服务器 v2/v3/v4,并实现了 http 轮询和 websocket等功能。这也使得我们能顺畅的在Unity3d上使用socket.io.

准备Unity工程

直接将这个库克隆下来,或者下载(Download ZIP)可以看到如下目录:
在这里插入图片描述

新建一个Unity工程,并将我们这里的文件夹复制到工程中的Assets\SocketIO文件夹下。

也可以通过Unity工程中的 Package Manager进行安装:复制此网址:然后在 Unity 中打开Window -> Package Manager -> 并单击(+) add package from git URL…
并将

https://github.com/itisnajim/SocketIOUnity.git

贴到地址框内。

这是在工程中,可以看到报错:
在这里插入图片描述

Assets\SocketIO\Samples\Sample\SocketManager.cs(4,22): error CS0234:
The type or namespace name ‘Newtonsoft’ does not exist in the
namespace ‘SocketIOClient’ (are you missing an assembly reference?)

大致意思是缺失’Newtonsoft’ ,经过研究发现socket.io-client-csharp中包含SocketIOClient.Newtonsoft.Json
在这里插入图片描述

将其下载放入工程Assets\SocketIO文件夹下后错误消除。

服务端

服务端有个案例脚本(SocketIO\Samples\Server\index.js)代码如下:

'use strict';

const http = require('http');
const socket = require('socket.io');
const server = http.createServer();
const port = 11100;

var io = socket(server, {
    pingInterval: 10000,
    pingTimeout: 5000
});

io.use((socket, next) => {
    if (socket.handshake.query.token === "UNITY") {
        next();
    } else {
        next(new Error("Authentication error"));
    }
});

io.on('connection', socket => {
  console.log('connection');

  setTimeout(() => {
    socket.emit('connection', {date: new Date().getTime(), data: "Hello Unity"})
  }, 1000);

  socket.on('hello', (data) => {
    console.log('hello', data);
    socket.emit('hello', {date: new Date().getTime(), data: data});
  });

  socket.on('spin', (data) => {
    console.log('spin');
    socket.emit('spin', {date: new Date().getTime(), data: data});
  });

  socket.on('class', (data) => {
    console.log('class', data);
    socket.emit('class', {date: new Date().getTime(), data: data});
  });
});


server.listen(port, () => {
  console.log('listening on *:' + port);
});

这里将其通过node.js启动起来。
Node.js的下载、安装以及环境配置在此就不赘述了,网上一搜一大堆。
在cmd命令行中跳转至Assets\SocketIO\Samples\Server目录,并执行npm install命令安装关联的包体:
在这里插入图片描述

安装完成后,输入node index执行脚本:
在这里插入图片描述

这就完成了服务端的运行。

运行案例

要Unity3d端能连上我们启动好的服务后台还需要修改一下Unity工程的SocketManager.cs脚本中的Uri地址,将其修改为:

var uri = new Uri("http://127.0.0.1:11100");

因为我们服务器后端监听的是 *:11100。

这样我们启动运行Unity工程,就能连接node.js 并可以进行通信:
在这里插入图片描述

这里先收到了后端返回的连接信息,点击按钮发送了类、旋转指令和其它json数据并获得了服务端的响应。只要自己定义数据和事件名称(EventName)就可以实现自己的功能了。

其它

发送信息

socket.Emit("eventName");socket.Emit("eventName", "Hello World");
socket.Emit("eventName", someObject);
socket.EmitStringAsJSON("eventName", "{\"foo\": \"bar\"}");
await client.EmitAsync("hi", "socket.io"); // Here you should make the method async

接收信息

socket.On("eventName", (response) =>
{
    /* Do Something with data! */
    var obj = response.GetValue<SomeClass>();
});

连接/断开

socket.Connect();
await socket.ConnectAsync();
socket.Disconnect();
await socket.DisconnectAsync();

主线程问题

如果要使用 Unity 游戏对象(例如:旋转对象)或使用 PlayerPrefs 系统保存数据,请使用以下命令:

// Set (unityThreadScope) the thread scope function where the code should run.
// Options are: .Update, .LateUpdate or .FixedUpdate, default: UnityThreadScope.Update
socket.unityThreadScope = UnityThreadScope.Update; 
// "spin" is an example of an event name.
socket.OnUnityThread("spin", (response) =>
{
    objectToSpin.transform.Rotate(0, 45, 0);
});

或者

 socket.OnAnyInUnityThread((name, response) =>
 {
     Debug.Print("Received On " + name + " : " + response.GetValue().GetRawText() + "\n");
  });

再或者

socket.On("spin", (response) =>
{
    UnityThread.executeInUpdate(() => {
        objectToSpin.transform.Rotate(0, 45, 0);
    });
    /*     or      UnityThread.executeInLateUpdate(() => { ... });    or     UnityThread.executeInFixedUpdate(() => { ... });    */
});

版本问题

虽然该库?支持 socket.io 服务器 v2/v3/v4等版本,但是使用不同版本需要不同的设置,这里也是我走了很长弯路的地方。这就需要设置这个EIO:
在这里插入图片描述

如果您的服务器使用的是 socket.io 服务器 v2.x,请明确设置为 3。

这里我的服务器端他们刚好使用的就是2.x版本所以造成怎么都连接不上。 我的设置如下:

        var uri = new Uri("https://127.0.0.1:11100");
        socket = new SocketIOUnity(uri, new SocketIOOptions
        {
            Query = new Dictionary<string, string>
                {
                    {"code", SystemInfo.deviceUniqueIdentifier}
                }
            ,
            EIO = 3,
            //ExtraHeaders = header,
            Transport = SocketIOClient.Transport.TransportProtocol.WebSocket
        }); 

工程

https://download.csdn.net/download/qq_33789001/87366117

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
要在C#中调用Node.js,你可以使用`Process`类来启动一个Node.js进程,并通过标准输入输出与其进行通信。 下面是一个简单的示例代码,演示了如何在C#中调用Node.js并执行一个简单的JavaScript脚本: ```csharp using System; using System.Diagnostics; class Program { static void Main() { // 创建一个Process对象,用于启动Node.js进程 Process nodeProcess = new Process(); // 设置要启动的Node.js可执行文件路径和脚本文件路径 nodeProcess.StartInfo.FileName = "node"; nodeProcess.StartInfo.Arguments = "path/to/your/script.js"; // 启用输入输出重定向,以便与Node.js进程进行通信 nodeProcess.StartInfo.UseShellExecute = false; nodeProcess.StartInfo.RedirectStandardInput = true; nodeProcess.StartInfo.RedirectStandardOutput = true; // 启动Node.js进程 nodeProcess.Start(); // 向Node.js进程发送输入 nodeProcess.StandardInput.WriteLine("Hello from C#!"); // 读取Node.js进程的输出 string output = nodeProcess.StandardOutput.ReadToEnd(); // 输出Node.js进程的结果 Console.WriteLine("Output from Node.js: " + output); // 等待Node.js进程结束 nodeProcess.WaitForExit(); } } ``` 以上代码中,你需要将`path/to/your/script.js`替换为你的JavaScript脚本文件的路径。你可以在`StandardInput`属性上使用`WriteLine`方法向Node.js进程发送输入,并通过`StandardOutput`属性读取Node.js进程的输出。 请注意,为了使这个示例工作,你需要确保已经正确安装了Node.js,并且可以在命令行中使用`node`命令。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十幺卜入

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值