Unity-Mirror网络框架-从入门到精通之Basic示例

文章目录

    • 前言
    • Basic示例
    • 场景元素
    • 预制体元素
    • 代码逻辑
      • BasicNetManager
      • Player逻辑
        • SyncVars属性
        • Server逻辑
        • Client逻辑
      • PlayerUI逻辑
    • 最后

前言

在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架,专为多人游戏开发设计。它使得开发者能够轻松实现网络连接、数据同步和游戏状态管理。本文将深入介绍Mirror的基本概念、如何与其他网络框架进行比较,以及如何从零开始创建一个使用Mirror的简单网络项目。
在这里插入图片描述

Basic示例

运行结果如下:
在这里插入图片描述
Basic示例是Mirror的最简单的示例,就展示了一个Player玩家的登录UI状态,
但是它却反应了Mirror框架的所有使用流程,可谓麻雀虽小,五脏俱全。
也从正面反应了,Mirror的简单易用性。

场景元素

我们打开场景,可以看到Basic场景中元素很少,除了一个NetworkManager,就是一个MainPanel的UI页面。
NetworkManager:即Mirror启动所需的网络管理器,有且必须有一个。
MainPanel:是用于存放玩家登录后的玩家UI图标的容器而已。
在这里插入图片描述

预制体元素

Basic场景用到的预制体,只有两个,
Player:代表登录后的玩家实体,如果玩家有移动,战斗等逻辑,就在它上面写
PlayerUI:代表玩家登录后,在UI显示的玩家图标,一个Player对应一个PlayerUI。
在这里插入图片描述

代码逻辑

BasicNetManager

namespace Mirror.Examples.Basic
{[AddComponentMenu("")]public class BasicNetManager : NetworkManager{public override void OnServerAddPlayer(NetworkConnectionToClient conn){base.OnServerAddPlayer(conn);Player.ResetPlayerNumbers();}public override void OnServerDisconnect(NetworkConnectionToClient conn){base.OnServerDisconnect(conn);Player.ResetPlayerNumbers();}}
}

BasicNetManager,继承了NetworkManager,因为NetworkManager只是包括了网络管理器的一些基本功能,比如:保持连接,维持NetworkIdentity的同步等基本网络同步功能。
Mirror给我们提供的很多Sample示例,其实都重写了NetworkManager,给我们展示了实现不同类型的项目,如何扩展NetworkManager。
NetworkManager内部有很多的生命周期函数,我们可以重写,并实现自己的目的。
比如这里,重写了OnServerAddPlayer和OnServerDisconnect。分别代表,客户端玩家连接上服务器和断开连接服务器。然后调用Player的函数,更新玩家Number显示。

Player逻辑

Player继承自NetworkBehaviour,是一个网络单元的行为组件。
我们都知道Unity是组件式编程,任何游戏对象如果想实现游戏逻辑,都可以由N个组件组成。
同理,在Mirror中,任何物体想要被同步,必须添加NetworkIdentity组件,代表是一个网络单元,然后只要这个网路单元,想实现其他的同步逻辑,比如属性,RPC调用等行为,就必须添加NetworkBehaviour组件才能实现, 而Player就是一个NetworkBehaviour,实现了Player应有的属性同步以及UI图标刷新功能。

SyncVars属性

Mirror提供了一种非常便利的属性同步机制,即[SyncVar],只要一个属性添加了SyncVar属性,就可以在不同的客户端之间实现同步。
如果添加了Hook参数,还可以实现参数变化时的函数回调。如下代码所示:
playerNumber
playerColor
playerData
这三个参数是可以在网络中进行同步的,且修改后,每个玩家的UI图标的数值都会发生自动更新。

#region SyncVars[Header("SyncVars")]/// <summary>/// This is appended to the player name text, e.g. "Player 01"/// </summary>[SyncVar(hook = nameof(PlayerNumberChanged))]public byte playerNumber = 0;/// <summary>/// Random color for the playerData text, assigned in OnStartServer/// </summary>[SyncVar(hook = nameof(PlayerColorChanged))]public Color32 playerColor = Color.white;/// <summary>/// This is updated by UpdateData which is called from OnStartServer via InvokeRepeating/// </summary>[SyncVar(hook = nameof(PlayerDataChanged))]public ushort playerData = 0;// This is called by the hook of playerNumber SyncVar abovevoid PlayerNumberChanged(byte _, byte newPlayerNumber){OnPlayerNumberChanged?.Invoke(newPlayerNumber);}// This is called by the hook of playerColor SyncVar abovevoid PlayerColorChanged(Color32 _, Color32 newPlayerColor){OnPlayerColorChanged?.Invoke(newPlayerColor);}// This is called by the hook of playerData SyncVar abovevoid PlayerDataChanged(ushort _, ushort newPlayerData){OnPlayerDataChanged?.Invoke(newPlayerData);}#endregion
Server逻辑

Server逻辑什么意思呢?为什么要拆分Server和Client逻辑呢?
这就要在此强调下Mirror的网络架构了,我再开篇的:Unity-Mirror网络框架-从入门到精通之Mirror简介中,专门介绍了Mirror的网络结构和传统的CS网络结构的差异,我们不能像写传统的CS架构下客户端一样
去写Mirror框架中的逻辑。因为Mirror框架中,我们写的代码实际是包含了服务器和客户端,双端逻辑的,这样就省去了一个Server端。只是我们在开发时要注意。有些逻辑需要写在Server中,有些需要写在Client中。这一点是非常重要的。

如下代码所示:
可以理解为这些逻辑属于服务器执行的逻辑。
OnStartServer,就是当一个客户端玩家,在服务器上被激活时,一般用于初始化一些同步网络属性,默认情况下SyncVar属性的值,只能在Server下被修改,然后同步给所有客户端。

[ServerCallback]属性修饰了两个函数ResetPlayerNumber和UpdateData,
代表这两个函数,只能在Server端被调用,客户端是 不能调用的。

        #region Server/// <summary>/// This is invoked for NetworkBehaviour objects when they become active on the server./// <para>This could be triggered by NetworkServer.Listen() for objects in the scene, or by NetworkServer.Spawn() for objects that are dynamically created.</para>/// <para>This will be called for objects on a "host" as well as for object on a dedicated server.</para>/// </summary>public override void OnStartServer(){base.OnStartServer();// Add this to the static Players ListplayersList.Add(this);// set the Player Color SyncVarplayerColor = Random.ColorHSV(0f, 1f, 0.9f, 0.9f, 1f, 1f);// set the initial player dataplayerData = (ushort)Random.Range(100, 1000);// Start generating updatesInvokeRepeating(nameof(UpdateData), 1, 1);}// This is called from BasicNetManager OnServerAddPlayer and OnServerDisconnect// Player numbers are reset whenever a player joins / leaves[ServerCallback]internal static void ResetPlayerNumbers(){byte playerNumber = 0;foreach (Player player in playersList)player.playerNumber = playerNumber++;}// This only runs on the server, called from OnStartServer via InvokeRepeating[ServerCallback]void UpdateData(){playerData = (ushort)Random.Range(100, 1000);}/// <summary>/// Invoked on the server when the object is unspawned/// <para>Useful for saving object data in persistent storage</para>/// </summary>public override void OnStopServer(){CancelInvoke();playersList.Remove(this);}#endregion
Client逻辑

Client逻辑,就是纯粹的客户端显示逻辑。
比如:
OnStartClient.,当玩家在客户端激活时,创建一个指定的UI显示玩家信息
OnStartLocalPlayer:当本机玩家连接成功后,显示画布UI,代表自己登录成功了

 #region Client/// <summary>/// Called on every NetworkBehaviour when it is activated on a client./// <para>Objects on the host have this function called, as there is a local client on the host. The values of SyncVars on object are guaranteed to be initialized correctly with the latest state from the server when this function is called on the client.</para>/// </summary>public override void OnStartClient(){// Instantiate the player UI as child of the Players PanelplayerUIObject = Instantiate(playerUIPrefab, CanvasUI.GetPlayersPanel());playerUI = playerUIObject.GetComponent<PlayerUI>();// wire up all events to handlers in PlayerUIOnPlayerNumberChanged = playerUI.OnPlayerNumberChanged;OnPlayerColorChanged = playerUI.OnPlayerColorChanged;OnPlayerDataChanged = playerUI.OnPlayerDataChanged;// Invoke all event handlers with the initial data from spawn payloadOnPlayerNumberChanged.Invoke(playerNumber);OnPlayerColorChanged.Invoke(playerColor);OnPlayerDataChanged.Invoke(playerData);}/// <summary>/// Called when the local player object has been set up./// <para>This happens after OnStartClient(), as it is triggered by an ownership message from the server. This is an appropriate place to activate components or functionality that should only be active for the local player, such as cameras and input.</para>/// </summary>public override void OnStartLocalPlayer(){// Set isLocalPlayer for this Player in UI for background shadingplayerUI.SetLocalPlayer();// Activate the main panelCanvasUI.SetActive(true);}/// <summary>/// Called when the local player object is being stopped./// <para>This happens before OnStopClient(), as it may be triggered by an ownership message from the server, or because the player object is being destroyed. This is an appropriate place to deactivate components or functionality that should only be active for the local player, such as cameras and input.</para>/// </summary>public override void OnStopLocalPlayer(){// Disable the main panel for local playerCanvasUI.SetActive(false);}/// <summary>/// This is invoked on clients when the server has caused this object to be destroyed./// <para>This can be used as a hook to invoke effects or do client specific cleanup.</para>/// </summary>public override void OnStopClient(){// disconnect event handlersOnPlayerNumberChanged = null;OnPlayerColorChanged = null;OnPlayerDataChanged = null;// Remove this player's UI objectDestroy(playerUIObject);}#endregion

PlayerUI逻辑

PlayerUI比较简单,当Player属性发行变化时,会调用对应的函数,更新PlayerUI显示。

Player中有对应的事件绑定

            // Instantiate the player UI as child of the Players PanelplayerUIObject = Instantiate(playerUIPrefab, CanvasUI.GetPlayersPanel());playerUI = playerUIObject.GetComponent<PlayerUI>();// wire up all events to handlers in PlayerUIOnPlayerNumberChanged = playerUI.OnPlayerNumberChanged;OnPlayerColorChanged = playerUI.OnPlayerColorChanged;OnPlayerDataChanged = playerUI.OnPlayerDataChanged;

PlayerUI中只需要更新Text的显示即可

namespace Mirror.Examples.Basic
{public class PlayerUI : MonoBehaviour{[Header("Player Components")]public Image image;[Header("Child Text Objects")]public Text playerNameText;public Text playerDataText;// Sets a highlight color for the local playerpublic void SetLocalPlayer(){// add a visual background for the local player in the UIimage.color = new Color(1f, 1f, 1f, 0.1f);}// This value can change as clients leave and joinpublic void OnPlayerNumberChanged(byte newPlayerNumber){playerNameText.text = string.Format("Player {0:00}", newPlayerNumber);}// Random color set by Player::OnStartServerpublic void OnPlayerColorChanged(Color32 newPlayerColor){playerNameText.color = newPlayerColor;}// This updates from Player::UpdateData via InvokeRepeating on serverpublic void OnPlayerDataChanged(ushort newPlayerData){// Show the data in the UIplayerDataText.text = string.Format("Data: {0:000}", newPlayerData);}}
}

最后

最后运行成功后,会显示玩家编号和信息,代表玩家连接成功。
在此基础上,我们可以自己发挥想象力扩展一下如:
玩家昵称,在PlayeUI上显示。
用一个模型代表玩家身体,可以再Player中做玩家的位移等。
在这里插入图片描述
好了,这篇文章就到这里,希望对你有所帮助

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIA - APLIC之二

本文属于《 RISC-V指令集基础系列教程》之一,欢迎查看其它文章。 对于APLIC实现的每一个中断域,都存在一个独享的内存映射的控制区域,用来处理该中断域的中断。 该控制区域大小是由4KB的倍数,并与4KB地址边界对齐,最小的有效控制区域是16KB。 接下来,本文将详细讲解,AP…

设计模式之访问者模式:一楼千面 各有玄机

~犬&#x1f4f0;余~ “我欲贱而贵&#xff0c;愚而智&#xff0c;贫而富&#xff0c;可乎&#xff1f; 曰&#xff1a;其唯学乎” 一、访问者模式概述 \quad 江湖中有一个传说&#xff1a;在遥远的东方&#xff0c;有一座神秘的玉楼。每当武林中人来访&#xff0c;楼中的各个房…

SAP月结、年结前重点检查事项(后勤与财务模块)

文章目录 一、PP生产模块相关的事务检查二、SD销售模块相关的事务检查:三、MM物料管理模块相关的事务检查四、FICO财务模块相关的事务检查五、年结前若干注意事项【SAP系统PP模块研究】 #SAP #生产订单 #月结 #年结 一、PP生产模块相关的事务检查 1、月末盘点后,生产用料的…

JVM实战—6.频繁YGC和频繁FGC的后果

大纲 1.JVM GC导致系统突然卡死无法访问 2.什么是Young GC什么是Full GC 3.Young GC、Old GC和Full GC的发生情况 4.频繁YGC的案例(G1解决大内存YGC过慢) 5.频繁FGC的案例(YGC存活对象S区放不下) 6.问题汇总 1.JVM GC导致系统突然卡死无法访问 (1)基于JVM运行的系统最怕…

蓝牙|软件 Qualcomm S7 Sound Platform开发系列之初级入门指南

本文适用范围 ADK24.2~ 问题/功能描述 S7开发环境搭建与编译介绍 实现方案 本文介绍适用于windows平台Application部分,audio ss的说明会在下一篇文章在做说明,Linux平台如果不进行AI算法的开发,个人认知是没有必要配置,若是做服务器倒是不错的选择.因为编译完成后烧录调试还…

LabVIEW冷却风机性能测试系统

开发了基于LabVIEW软件及LabSQL工具包的冷却风机性能测试系统。系统通过高效的数据库访问技术&#xff0c;实现了对冷却风机测试过程中关键性能数据的采集、存储与管理&#xff0c;优化了测试流程并提升了数据处理的效率。 ​ 项目背景 在工业生产和科研测试中&#xff0c;准…

C 实现植物大战僵尸(四)

C 实现植物大战僵尸&#xff08;四&#xff09; C 实现植物大战僵尸&#xff0c;完结撒花&#xff08;还有个音频稍卡顿的性能问题&#xff0c;待有空优化解决&#xff09;。目前基本的功能模块已经搭建好了&#xff0c;感兴趣的友友可自行尝试编写后续游戏内容 因为 C 站不能…

车间管理:掌握方法,有效应对浪费

在制造企业中&#xff0c;车间的有效管理对于提高生产效率、降低成本以及提升产品质量至关重要&#xff0c;然而面对外部激烈的市场竞争&#xff0c;利润微薄&#xff0c;内部车间却充满了各种浪费&#xff0c;企业管理者头痛不已&#xff0c;如果能有效改进内部车间浪费&#…

Logo设计免费生成器工具:轻松创建独特标志

在当今的商业世界中&#xff0c;一个独特且引人注目的Logo是任何企业或品牌的身份象征。它不仅代表了公司的形象&#xff0c;还传达了公司的价值观和使命。然而&#xff0c;对于许多初创企业或小型企业来说&#xff0c;聘请专业设计师来设计一个Logo可能是一笔不小的开销。这时…

【智行安全】基于Synaptics SL1680的AI疲劳驾驶检测方案

随著车载技术的快速进步&#xff0c;驾驶安全越来越受到重视&#xff0c;而疲劳驾驶是造成交通事故的重要原因之一。传统的驾驶监控技术因精度不足或反应迟缓&#xff0c;无法满足实时监测需求。因此&#xff0c;结合人工智能技术的疲劳驾驶检测系统成为行业新方向&#xff0c;…

uni-ui样式修改

因为之前官网uni-ui有些组件的样式不好看&#xff0c;所以要做一些调整&#xff0c;做个记录。用分段器举例~ 官网原生样式 调整后的 首先找到我们的static文件夹&#xff0c;里面一般存着项目的全局样式文件&#xff0c;没有的话自己创一个 uniui.scss /deep/ .segmented-con…

大模型WebUI:Gradio全解系列9——Additional Features:补充特性(下)

大模型WebUI&#xff1a;Gradio全解系列9——Additional Features&#xff1a;补充特性&#xff08;下&#xff09; 前言本篇摘要8. Additional Features&#xff1a;补充特性8.5 分享demo8.5.1 嵌入托管 Spaces8.5.2 使用 Web Components 嵌入8.5.3 Embedding with IFrames 8.…

计算机网络 (17)点对点协议PPP

一、PPP协议的基本概念 PPP协议最初设计是为两个对等节点之间的IP流量传输提供一种封装协议&#xff0c;它替代了原来非标准的第二层协议&#xff08;如SLIP&#xff09;。在TCP/IP协议集中&#xff0c;PPP是一种用来同步调制连接的数据链路层协议&#xff08;OSI模式中的第二层…

HTML5滑块(Slider)

HTML5 的滑块&#xff08;Slider&#xff09;控件允许用户通过拖动滑块来选择数值。以下是如何实现一个简单的滑块组件的详细说明。 HTML5 滑块组件 1. 基本结构 使用 <input type"range"> 元素可以创建一个滑块。下面是基本实现的代码示例&#xff1a; <…

在Linux上获取MS(如Media Server)中的RTP流并录制为双轨PCM格式的WAV文件

在Linux上获取MS(如Media Server)中的RTP流并录制为双轨PCM格式的WAV文件 一、RTP流与WAV文件格式二、实现步骤三、伪代码示例四、C语言示例代码五、关键点说明六、总结在Linux操作系统上,从媒体服务器(如Media Server,简称MS)获取RTP(Real-time Transport Protocol)流…

Unity3D仿星露谷物语开发12之创建道具列表

1、目标 道具是游戏的核心部分&#xff0c;道具包括你可以拾取的东西&#xff0c;你可以使用的工具和你能种的东西等。 本节就是创建道具的信息类。同时了解ScriptableObject类的使用。 2、创建道具枚举类 修改Assets -> Scripts -> Enums.cs脚本&#xff0c; 新增如…

华为云Welink数据怎么连接到小满CRM?

Welink是什么&#xff1f;好用吗&#xff1f; 华为云WeLink是华为内部打磨多年的协同办公平台、远程办公软件、移动办公平台、协同办公软件&#xff0c;来源华为19万员工的数字化办公实践&#xff0c;融合多屏协同、打卡、报销、考勤、审批、企业网盘、IM消息、邮件、视频会议…

借助 FinClip 跨端技术探索鸿蒙原生应用开发之旅

在当今数字化浪潮汹涌澎湃的时代&#xff0c;移动应用开发领域正经历着深刻的变革与创新。鸿蒙操作系统的崛起&#xff0c;以其独特的分布式架构和强大的性能表现&#xff0c;吸引了众多开发者的目光。而FinClip 跨端技术的出现&#xff0c;为开发者涉足鸿蒙原生应用开发提供了…

IDEA+Docker一键部署项目SpringBoot项目

文章目录 1. 部署项目的传统方式2. 前置工作3. SSH配置4. 连接Docker守护进程5. 创建简单的SpringBoot应用程序6. 编写Dockerfile文件7. 配置远程部署 7.1 创建配置7.2 绑定端口7.3 添加执行前要运行的任务 8. 部署项目9. 开放防火墙的 11020 端口10. 访问项目11. 可能遇到的问…

Excel文件恢复教程:快速找回丢失数据!

Excel文件恢复位置在哪里&#xff1f; Excel是微软开发的电子表格软件&#xff0c;它为处理数据和组织工作提供了便捷。虽然数据丢失的问题在数字时代已经司空见惯&#xff0c;但对于某些用户来说&#xff0c;恢复未保存/删除/丢失的Excel文件可能会很困难&#xff0c;更不用说…