首页 > 编程语言 >通过示例在 Unity 和 NodeJS 上的游戏中创建安全、快速的多人游戏

通过示例在 Unity 和 NodeJS 上的游戏中创建安全、快速的多人游戏

时间:2024-09-26 22:02:59浏览次数:1  
标签:const 游戏 NodeJS buffer 示例 服务器 data id 客户端

介绍规划多人游戏开发方法 - 在整个项目的进一步开发中发挥着最重要的作用之一,因为它包含了我们在创建真正高质量的产品时应该考虑的许多标准。在今天的宣言教程中,我们将看一个方法示例,该方法使我们能够创建真正快速的游戏,同时尊重所有安全和反违规规则。所以,让我们定义我们的主要标准:多人游戏需要一种特殊的方法来管理网络同步,尤其是在实时情况下。 二进制协议用于加速客户端之间的数据同步,反应字段将有助于以最小的延迟和节省内存来更新玩家位置。服务器权限是一项重要原则,关键数据仅在服务器上处理,确保游戏完整性并防止作弊。然而,为了让我们最大限度地提高性能 - 服务器只进行关键更新,剩下的交给客户端反作弊。实施客户端反投诉,以便在服务器上不增加负载的情况下处理不太关键的数据。 架构的主要组成部分客户端(unity):客户端负责显示游戏状态,将玩家操作发送到服务器并从服务器接收更新。这里还使用反应字段来动态更新玩家位置。服务器端(node.js):服务器处理关键数据(例如,移动、碰撞和玩家动作)并将更新发送到所有连接的客户端。非关键数据可以在客户端上处理并使用服务器转发到其他客户端。二进制协议:二进制数据序列化用于减少传输的数据量并提高性能。同步:提供客户端之间数据的快速同步,以最大程度地减少延迟并确保流畅的游戏体验。客户端反作弊:它用于我们可以在客户端上更改并发送给其他客户端的数据。 第 1 步:在 node.js 中实现服务器首先,您需要在 node.js 上设置一个服务器。服务器将负责所有关键计算并将更新的数据传输给玩家。安装环境要在 node.js 上创建服务器,请安装必要的依赖项:mkdir multiplayer-game-servercd multiplayer-game-servernpm init -ynpm install socket.io登录后复制socket.io可以轻松地使用web套接字实现客户端和服务器之间的实时双向通信。基本服务器实现让我们创建一个简单的服务器,它将处理客户端连接、检索数据、计算关键状态并在所有客户端之间同步它们。// create a simple socket io serverconst io = require('socket.io')(3000, { cors: { origin: '*' }});// simple example of game stateslet gamestate = {};let playerspeedconfig = { maxx: 1, maxy: 1, maxz: 1};// work with new connectionio.on('connection', (socket) =&gt; { console.log('player connected:', socket.id); // initialize player state for socket id gamestate[socket.id] = { x: 0, y: 0, z: 0 }; // work with simple player command for movement socket.on('playermove', (data) =&gt; { const { id, dx, dy, dz } = parseplayermove(data); // check maximal values if(dx &gt; playerspeedconfig.maxx) dx = playerspeedconfig.maxx; if(dy &gt; playerspeedconfig.maxy) dx = playerspeedconfig.maxy; if(dz &gt; playerspeedconfig.maxz) dx = playerspeedconfig.maxz; // update game state for current player gamestate[id].x += dx; gamestate[id].y += dy; gamestate[id].z += dz; // send new state for all clients const updateddata = serializegamestate(gamestate); io.emit('gamestateupdate', updateddata); }); // work with unsafe data socket.on('dataupdate', (data) =&gt; { const { id, unsafe } = parseplayerunsafe(data); // update game state for current player gamestate[id].unsafevalue += unsafe; // send new state for all clients const updateddata = serializegamestate(gamestate); io.emit('gamestateupdate', updateddata); }); // work with player disconnection socket.on('disconnect', () =&gt; { console.log('player disconnected:', socket.id); delete gamestate[socket.id]; });});// simple parse our binary datafunction parseplayermove(buffer) { const id = buffer.tostring('utf8', 0, 16); // player id (16 bit) const dx = buffer.readfloatle(16); // delta x const dy = buffer.readfloatle(20); // delta y const dz = buffer.readfloatle(24); // delta z return { id, dx, dy, dz };}// simple parse of unsafe datafunction parseplayerunsafe(buffer) { const id = buffer.tostring('utf8', 0, 16); // player id (16 bit) const unsafe = buffer.readfloatle(16); // unsafe float return { id, unsafe };}// simple game state serialization for binary protocolfunction serializegamestate(gamestate) { const buffers = []; for (const [id, data] of object.entries(gamestate)) { // player id const idbuffer = buffer.from(id, 'utf8'); // position (critical) buffer const posbuffer = buffer.alloc(12); posbuffer.writefloatle(data.x, 0); posbuffer.writefloatle(data.y, 4); posbuffer.writefloatle(data.z, 8); // unsafe data buffer const unsafebuffer = buffer.alloc(4); unsafebuffer.writefloatle(data.unsafevalue, 0); // join all buffers buffers.push(buffer.concat([idbuffer, posbuffer, unsafebuffer])); } return buffer.concat(buffers);}登录后复制此服务器执行以下操作:处理客户端连接。接收二进制格式的玩家移动数据,验证它,更新服务器上的状态并将其发送到所有客户端。以最小延迟同步游戏状态,使用二进制格式来减少数据量。简单地转发来自客户端的不安全数据。要点:服务器权限:所有重要数据均在服务器上处理和存储。客户端仅发送操作命令(例如,位置变化增量)。二进制数据传输:使用二进制协议可以节省流量并提高网络性能,特别是对于频繁的实时数据交换。 第2步:在unity上实现客户端部分现在让我们在 unity 上创建一个与服务器交互的客户端部分。要将 unity 连接到 socket.io 上的服务器,您需要连接专为 unity 设计的库。在这种情况下,我们不受任何特定实现的约束(事实上它们都是相似的),而只是使用一个抽象示例。使用反应字段进行同步我们将使用反应字段来更新玩家位置。这将使我们能够更新状态,而无需通过 update() 方法检查每个帧中的数据。当数据状态发生变化时,反应字段会自动更新游戏中对象的视觉表示。要获得反应性属性功能,您可以使用 unirx。unity 上的客户端代码让我们创建一个脚本来连接到服务器、发送数据并通过反应字段接收更新。using UnityEngine;using SocketIOClient;using UniRx;using System;using System.Text;// Basic Game Client Implementationpublic class GameClient : MonoBehaviour{ // SocketIO Based Client private SocketIO client; // Our Player Reactive Position public ReactiveProperty<vector3> playerPosition = new ReactiveProperty<vector3>(Vector3.zero); // Client Initialization private void Start() { // Connect to our server client = new SocketIO("http://localhost:3000"); // Add Client Events client.OnConnected += OnConnected; // On Connected client.On("gameStateUpdate", OnGameStateUpdate); // On Game State Changed // Connect to Socket Async client.ConnectAsync(); // Subscribe to our player position changed playerPosition.Subscribe(newPosition =&gt; { // Here you can interpolate your position instead // to get smooth movement at large ping transform.position = newPosition; }); // Add Movement Commands Observable.EveryUpdate().Where(_ =&gt; Input.GetKey(KeyCode.W)).Subscribe(_ =&gt; ProcessInput(true)); Observable.EveryUpdate().Where(_ =&gt; Input.GetKey(KeyCode.S)).Subscribe(_ =&gt; ProcessInput(false)); } // On Player Connected private async void OnConnected(object sender, EventArgs e) { Debug.Log("Connected to server!"); } // On Game State Update private void OnGameStateUpdate(SocketIOResponse response) { // Get our binary data byte[] data = response.GetValue<byte>(); // Work with binary data int offset = 0; while (offset <h2> 第 3 步:优化同步和性能</h2><p><strong>为了确保流畅的游戏体验并最大程度地减少同步期间的延迟,建议:</strong></p><ol><li><strong>使用插值:</strong>客户端可以使用插值来平滑服务器更新之间的移动。这可以补偿较小的网络延迟。</li><li><strong>批量数据发送:</strong>不要按每一步发送数据,而是使用批量发送。例如,每隔几毫秒发送一次更新,这将减少网络负载。 </li><li><strong>降低更新频率:</strong>将发送数据的频率降低到合理的最低限度。例如,对于大多数游戏来说,每秒更新 20-30 次可能就足够了。</li></ol><h2> 如何简化二进制协议的使用?</h2><p>为了简化您使用二进制协议的工作 - 创建数据处理的基本原理以及与其交互的方案。</p><p><strong>对于我们的示例,我们可以采用一个基本协议,其中:</strong><br>1) 前 4 位是用户发出的请求的最大值(例如 0 - 移动玩家,1 - 射击等);<br>2) 接下来的 16 位是我们客户的 id。<br>3) 接下来我们填充通过循环传递的数据(一些网络变量),其中存储变量的 id、到下一个变量开头的偏移量(以字节为单位)、变量的类型和它的价值。</p><p>为了方便版本和数据控制 - 我们可以以方便的格式(json / xml)创建客户端-服务器通信模式,并从服务器下载一次,以便根据该模式进一步解析我们的二进制数据以获得所需的内容我们的 api 版本。</p><h2> 客户端反作弊</h2><p>在服务器上处理所有数据是没有意义的,其中一些数据更容易在客户端修改并发送到其他客户端。</p><p>为了让你在这个方案中更加安全 - 你可以使用客户端防黑客系统来防止内存黑客 - 例如,我的 gameshield - 一个免费的开源解决方案。</p><h2> 结论</h2><p>我们举了一个简单的例子,在 unity 上使用 node.js 服务器开发多人游戏,所有关键数据都在服务器上处理,以确保游戏的完整性。使用二进制协议传输数据有助于优化流量,而 unity 中的反应式编程可以轻松同步客户端状态,而无需使用 update() 方法。</p><p>这种方法不仅可以提高游戏性能,还可以通过确保所有关键计算都在服务器而不是客户端上执行来增强对作弊的保护。</p><p><strong>当然,一如既往地感谢您阅读这篇文章。如果您在组织多人项目架构方面仍有任何疑问或需要帮助 - 我邀请您加入我的 discord</strong></p><hr><p><strong>您还可以在我的困境中为我提供很多帮助,并支持发布新文章以及为开发人员免费提供的库和资源:</strong></p><p><strong>我的不和谐</strong> | <strong>我的博客</strong> | <strong>我的 <a style="color:#f60; text-decoration:underline;" href="https://www.php.cn/zt/15841.html" target="_blank">git</a>hub</strong></p><p><strong>btc:</strong> bc1qef2d34r4xkrm48zknjdjt7c0ea92ay9m2a7q55<br><br><strong>eth:</strong> 0x1112a2ef850711df4de9c432376f255f416ef5d0<br><strong><a style="color:#f60; text-decoration:underline;" href="https://www.php.cn/zt/94398.html" target="_blank">usdt</a> (trc20):</strong>trf7sli6trtnau6k3pvvy61bzqkhxdcrlc</p> </byte></vector3></vector3>登录后复制以上就是通过示例在 Unity 和 NodeJS 上的游戏中创建安全、快速的多人游戏的详细内容,更多请关注我的其它相关文章!

标签:const,游戏,NodeJS,buffer,示例,服务器,data,id,客户端
From: https://www.cnblogs.com/aow054/p/18434531

相关文章

  • 解决 Nodejs 中的“Punycode Module is Deprecated”问题
    大家好,我叫asimkhan,目前是metamelon的全栈开发人员。最近,我在为naseebi.com(一个婚姻移动和web应用程序)项目工作时遇到了一个令人沮丧的问题。该问题涉及node.js中punycode模块的弃用,我想与您分享我的经验和解决方案。问题在应用程序中使用配置文件创建功能时,我......
  • 游戏开发的未来(没有引擎!?)
    您无需等待游戏开发者设计关卡、角色或动作。??♂?相反,游戏会在你玩的过程中自动生成!这可能听起来像科幻小说,但由于谷歌开发的一项新技术,它正在成为现实。??♂?这个新的游戏引擎,称为“GameandGen”使用人工智能(AI)来动态创建游戏世界。?你不需要任何传统的编码来制作关卡或设......
  • 构建动态配色游戏:全面概述
    介绍在当今快节奏的数字世界中,创建引人入胜的交互式Web应用程序的能力是一项非常有价值的技能。为了提高我在前端开发和算法问题解决方面的熟练程度,我接受了构建颜色匹配游戏的挑战。这个项目不仅让我展示了我的技术能力,还为用户提供了愉快的教育体验。本文深入探讨了游戏背后的......
  • 文件系统:Nodejs `fs` 模块
    node.js中的fs(文件系统)模块是一个用于处理文件系统的强大工具,允许您与服务器上的文件和目录进行交互。它内置于node.js中,因此您无需安装任何额外的东西即可使用它。让我们来探讨一下fs的工作原理及其关键功能。1.什么是fs模块?fs模块提供了一个api,用于以紧密围绕标准......
  • 掌握循环的艺术:通过实际示例理解 For、While 和 Do While 结构
    循环是计算机编程中的一项基本且非常重要的功能,在每种编程语言中都发挥着同样重要的作用。循环主要分为三种类型:1.for2.while3.dowhile。我们先来了解一下什么是循环。循环是一种根据指定条件重复执行代码块的结构。您可能想知道,“如果循环可以达到此目的,为什么我们需要三种......
  • 掌握 Nodejs 中的电子邮件发送:分步指南
    发送电子邮件是许多web应用程序中的常见功能,无论是用于用户注册、密码重置还是营销活动。在本指南中,我们将向您展示如何在nodemailer模块的帮助下使用node.js发送电子邮件。我们将涵盖从设置项目到发送html电子邮件和处理附件的所有内容。1.开始使用您的node.js电......
  • package.json依赖包漏洞之nodejs-glob-parent正则表达式拒绝服务漏洞
    背景有个安全扫描的流水线,扫描了负责的项目之后,发现一些漏洞。需要说明的是,这个扫描只是针对package.json文件,扫的是依赖树,而不是项目源代码,也不是打包后的代码。但既然是漏洞,都是可以好好学习下的。 nodejs-glob-parent正则表达式拒绝服务漏洞(CVE-2020-28469)被扫描出来......
  • 基于nodejs+vue校园新闻网站[开题+源码+程序+论文]计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,互联网已成为人们获取信息、交流思想的重要平台。在高校环境中,信息的及时传播与共享对于促进学术交流、增强校园文化氛围、提升学生......
  • 基于nodejs+vue校园新闻网站[开题+源码+程序+论文]计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展和互联网的普及,校园信息化建设已成为提升教育质量、促进校园文化交流的重要途径。在当前数字化时代背景下,校园新闻作为连接师生、传......
  • 基于nodejs+vue校园学生会管理系统[开题+源码+程序+论文]计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景在当今数字化、信息化高速发展的时代,校园管理正逐步向智能化、高效化转型。学生会作为连接学校与学生之间的重要桥梁,其管理效率与服务质量直接影响到学生活......