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

文章目录

    • 前言
    • Additive Levels和Additive Scenes
    • Additive Levels
      • 场景介绍
      • Portal传送门
      • FadeInOut特效
    • Additive Scenes
      • 示例介绍
      • ZoneHandler
      • SceneMassage
    • 最后

前言

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

Additive Levels和Additive Scenes

在Unity Mirror中,Additive Levels和Additive Scenes虽然看起来相似,但它们的应用和功能存在一些区别。

  • Additive Levels 是一个示例,旨在展示如何使用附加场景进行场景管理和玩家移动。这个示例主要关注利用Scene Interest Management进行场景间的切换,例如通过传送门在不同的关卡之间传送玩家。它使得在不同的场景中,玩家只能看到并与同一场景中的其他玩家进行交互,而不影响其他场景的玩家。通过此示例,可以学习如何实现自定义的场景加载和淡入淡出效果,同时也演示了如何处理在多个场景间的玩家状态和同步 10 。

  • Additive Scenes 则是一个更广义的概念,指的是在Unity中同时加载多个场景的能力。通过添加添加场景,开发者可以在一个主场景中加载多个次要场景,以便实现更复杂的游戏逻辑和界面布局。添加场景通常用于开发大型游戏世界,而不必将整个游戏内容打包到一个单一场景中。

Additive Levels

在这里插入图片描述

场景介绍

我们可以看到 AdditiveScenes总共4个场景,分别是Offline,OnLine,SubLevel1,SubLevel,
Offline是启动场景,加载NetworkManager,然后进入OnLine场景
进入Online场景后,在额外添加两个SubLeve场景,但是SubLevel是处于未激活状态。


        /// Called on the server when a scene is completed loaded, when the scene load was initiated by the server with ServerChangeScene().
        public override void OnServerSceneChanged(string sceneName)
        {
            if (sceneName == onlineScene)
                StartCoroutine(ServerLoadSubScenes());
        }

        IEnumerator ServerLoadSubScenes()
        {
            foreach (string additiveScene in additiveScenes)
                yield return SceneManager.LoadSceneAsync(additiveScene, new LoadSceneParameters
                {
                    loadSceneMode = LoadSceneMode.Additive,
                    localPhysicsMode = LocalPhysicsMode.Physics3D 
                });

            subscenesLoaded = true;
        }

场景中有一个透明的传送区域,上面写着SubLevel1和SubLevel2,当我们控制WASD走过去,进入传送区域以后,就会加载指定的SubLevel场景为激活状态。

Portal传送门

        void OnTriggerEnter(Collider other)
        {
            if (isServer)
                StartCoroutine(SendPlayerToNewScene(other.gameObject));
        }

        [ServerCallback]
        IEnumerator SendPlayerToNewScene(GameObject player)
        {
            if (!player.TryGetComponent(out NetworkIdentity identity)) yield break;

            NetworkConnectionToClient conn = identity.connectionToClient;
            if (conn == null) yield break;

            // Tell client to unload previous subscene with custom handling (see NetworkManager::OnClientChangeScene).
            conn.Send(new SceneMessage { sceneName = gameObject.scene.path, sceneOperation = SceneOperation.UnloadAdditive, customHandling = true });

            // wait for fader to complete.
            yield return new WaitForSeconds(AdditiveLevelsNetworkManager.singleton.fadeInOut.GetFadeInTime());

            // Remove player after fader has completed
            NetworkServer.RemovePlayerForConnection(conn, RemovePlayerOptions.Unspawn);
            yield return null;

            // reposition player on server and client
            player.transform.position = startPosition;
            player.transform.LookAt(Vector3.up);

            // Move player to new subscene.
            SceneManager.MoveGameObjectToScene(player, SceneManager.GetSceneByPath(destinationScene));

            // Tell client to load the new subscene with custom handling (see NetworkManager::OnClientChangeScene).
            conn.Send(new SceneMessage { sceneName = destinationScene, sceneOperation = SceneOperation.LoadAdditive, customHandling = true });

            // Player will be spawned after destination scene is loaded
            NetworkServer.AddPlayerForConnection(conn, player);
        }

其实这个传送门核心代码就三句
从服务器移除传送玩家
1.NetworkServer.RemovePlayerForConnection(conn, RemovePlayerOptions.Unspawn);
移动玩家到新场景中
2.SceneManager.MoveGameObjectToScene(player, SceneManager.GetSceneByPath(destinationScene));
添加传送玩家到服务器
3.NetworkServer.AddPlayerForConnection(conn, player);

FadeInOut特效

传送效果,其实非常简单,就是一个Image遮罩的透明度变化。详细请参考代码。

        private IEnumerator FadeImage(float startAlpha, float endAlpha, float duration)
        {
            if (panelImage == null) yield break;

            if (isFading) yield break;

            // Short circuit if the alpha is already at endAlpha
            Color color = panelImage.color;
            if (Mathf.Approximately(color.a, endAlpha)) yield break;

            isFading = true;

            float elapsedTime = 0f;
            float fixedDeltaTime = Time.fixedDeltaTime;

            while (elapsedTime < duration)
            {
                elapsedTime += fixedDeltaTime;
                float alpha = Mathf.Lerp(startAlpha, endAlpha, elapsedTime / duration);
                panelImage.color = new Color(color.r, color.g, color.b, alpha);
                yield return new WaitForFixedUpdate();
            }

            // Ensure the final alpha value is set
            panelImage.color = new Color(color.r, color.g, color.b, endAlpha);

            isFading = false;
        }

Additive Scenes

示例介绍

该实例,默认只有服务端加载了SubScene场景,这样可以减少客户端的开销。
在这里插入图片描述
启动Server后,加载SubScene,仅在服务器上。

 public class AdditiveNetworkManager : NetworkManager
    {
        [Tooltip("Trigger Zone Prefab")]
        public GameObject Zone;
        public string[] subScenes;

        public override void OnStartServer()
        {
            base.OnStartServer();

            // load all subscenes on the server only
            StartCoroutine(LoadSubScenes());

            // Instantiate Zone Handler on server only
            Instantiate(Zone);
        }

        IEnumerator LoadSubScenes()
        {
            Debug.Log("Loading Scenes");

            foreach (string sceneName in subScenes)
                yield return SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
        }
    }

ZoneHandler

当Client的Player移动到指定碰撞区域后,会发送SceneMessage 消息给客户端,这时客户端才会加载对应的SubScene。

public class ZoneHandler : MonoBehaviour
    {
        [Scene]
        public string subScene;

        [ServerCallback]
        void OnTriggerEnter(Collider other)
        {
            // ignore collisions with non-Player objects
            if (!other.CompareTag("Player")) return;

            if (other.TryGetComponent(out NetworkIdentity networkIdentity))
            {
                SceneMessage message = new SceneMessage { sceneName = subScene, sceneOperation = SceneOperation.LoadAdditive };
                networkIdentity.connectionToClient.Send(message);
            }
        }

        [ServerCallback]
        void OnTriggerExit(Collider other)
        {
            // ignore collisions with non-Player objects
            if (!other.CompareTag("Player")) return;

            if (other.TryGetComponent(out NetworkIdentity networkIdentity))
            {
                SceneMessage message = new SceneMessage { sceneName = subScene, sceneOperation = SceneOperation.UnloadAdditive };
                networkIdentity.connectionToClient.Send(message);
            }
        }
    }

SceneMassage

客户端加载场景的机制是:
NetworkManager中有SceneMassage事件的监听
NetworkClient.RegisterHandler<SceneMessage>(OnClientSceneInternal, false);
接收到SceneMassage后,会自动加载场景

最后

综上所述,Additive Levels是一个具体的实现示例,重点展示如何在多人环境中通过附加场景管理和传送玩家,
而Additive Scenes则是Unity提供的一个更普遍的功能,支持在同一游戏会话中使用多个场景,并且可以通过服务器检测来决定客户端什么时候加载SubScene。达到客户端按需加载必要场景的目的。

通过理解这两者的差别,开发者可以更加有效地利用Unity的场景管理系统,以实现更复杂的游戏机制和体验。

好了,这篇文章就到这里,希望这篇文章对你有所帮助。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mac-docker配置

1.配置的文件路径 cd ~/.docker (base) zhangyaweimacbookair .docker % ls buildx cli-plugins config.json contexts daemon.json desktop-build mutagen run (base) zhangyaweimacbookair .docker % cat daemon.json## 重启docker服务 sudo systemctl daemon-reload sudo…

PHP进阶-在Ubuntu上搭建LAMP环境教程

本文将为您提供一个在Ubuntu服务器上搭建LAMP&#xff08;Linux, Apache, MySQL, PHP&#xff09;环境的完整指南。通过本文&#xff0c;您将学习如何安装和配置Apache、MySQL、PHP&#xff0c;并将您的PHP项目部署到服务器上。本文适用于Ubuntu 20.04及更高版本。 一、系统更新…

Elasticsearch(看这一篇就够了)

目录&#xff1a; Elasticsearch介绍正排索引和倒排索引Elasticsearch安装安装ES服务安装服务安装kibana 索引操作创建索引查询索引库修改索引库删除索引库 Elasticsearch常用操作文档操作新增文档查询文档删除文档根据id批量查询文档查询所有文档修改文档部分字段 域的属性分词…

嵌入式技术之Linux(Ubuntu) 一

一、Linux入门 1.硬件和操作系统以及用户的关系 一个传感器&#xff0c;获得数据后&#xff0c;需要向服务器发送数据。传感器传数据给上位机。 上位机需要一个程序来接收数据&#xff0c;那么这个上位机是什么机器&#xff1f; 我们的笔记本电脑就可以当成上位机。 两个手…

【实用技能】如何使用 .NET C# 中的 Azure Key Vault 中的 PFX 证书对 PDF 文档进行签名

TX Text Control 是一款功能类似于 MS Word 的文字处理控件&#xff0c;包括文档创建、编辑、打印、邮件合并、格式转换、拆分合并、导入导出、批量生成等功能。广泛应用于企业文档管理&#xff0c;网站内容发布&#xff0c;电子病历中病案模板创建、病历书写、修改历史、连续打…

oracle闪回恢复数据:(闪回查询,闪回表,闪回库,回收站恢复)

oracle的闪回查询&#xff0c;可以查询提交在表空间的闪回数据&#xff0c;并可以还原所查询的数据&#xff0c;用于恢复短时间内的delele 或者 update 误操作&#xff0c;非常方便&#xff0c;缺点是只能恢复大概几小时内的数据。 文章目录 概要闪回查询恢复数据的主要方法包括…

开放词汇检测新晋SOTA:地瓜机器人开源DOSOD实时检测算法

在计算机视觉领域&#xff0c;目标检测是一项关键技术&#xff0c;旨在识别图像或视频中感兴趣物体的位置与类别。传统的闭集检测长期占据主导地位&#xff0c;但近年来&#xff0c;开放词汇检测&#xff08;Open-Vocabulary Object Detection-OVOD 或者 Open-Set Object Detec…

【网络协议】静态路由详解

网络中的路由器通过以下两种方式之一发现远程网络&#xff1a; 静态配置路由动态路由协议 在本文&#xff0c;我们将学习关于静态路由的各种概念&#xff0c;例如如何配置静态路由、路由表如何进行决策、路由接口等相关知识。 文章目录 引言直连网络静态路由路由表原则原则1原…

(长期更新)《零基础入门 ArcGIS(ArcScene) 》实验七----城市三维建模与分析(超超超详细!!!)

城市三维建模与分析 三维城市模型已经成为一种非常普遍的地理空间数据资源,成为城市的必需品,对城市能化管理至关重要。语义信息丰富的三维城市模型可以有效实现不同领域数据与IS相信息的高层次集成及互操作,从而在城市规划、环境模拟、应急响应和辅助决策等众多领域公挥作用、…

计算机网络--路由器问题

一、路由器问题 1.计算下一跳 计算机网络--根据IP地址和路由表计算下一跳-CSDN博客 2.更新路由表 计算机网络--路由表的更新-CSDN博客 3.根据题目要求给出路由表 4.路由器收到某个分组&#xff0c;解释这个分组是如何被转发的 5.转发分组之路由器的选择 二、举个例子 …

通过Android Studio修改第三方jar包并重新生成jar包

最近接手了来自公司其他同事的一个Unity项目,里面有一个封装的jar包要改动一下,无奈关于这个jar包的原工程文件丢失了,于是自己动手来修改下jar包,并做下记录。 一、导入第三方jar包 1、新建项目EditJarDemo(项目名随便取) 2、新建libs文件夹,把你要修改的third.jar 复制…

33.3K 的Freqtrade:开启加密货币自动化交易之旅

“ 如何更高效、智能地进行交易成为众多投资者关注的焦点。” Freqtrade 是一款用 Python 编写的免费开源加密货币交易机器人。它就像一位不知疲倦的智能交易助手&#xff0c;能够连接到众多主流加密货币交易所&#xff0c;如 Binance、Bitmart、Bybit 等&#xff08;支…

计算机网络 (26)互联网的路由选择协议

一、路由选择协议的基本概念 路由选择协议是计算机网络中用于确定数据包在网络中传输路径的一种协议。它帮助路由器构建和维护路由表&#xff0c;以便根据目的地址将数据包转发到正确的下一跳路由器。路由选择协议分为静态路由选择协议和动态路由选择协议两大类。 二、静态路由…

【MySQL实战】Centos安装MySQL

在CentOS上安装MySQL以及进行性能分析&#xff1a;2种方式&#xff0c;第一种直接装&#xff1b;第二种用docker安装&#xff1a; 直接安装MySQL 首先&#xff0c;更新系统软件包列表&#xff1a; sudo yum update然后&#xff0c;安装MySQL服务器&#xff1a; sudo yum in…

centOS7

特殊权限 set_uid 赋予所有者身份 chmod us 文件 set_gid 赋予所有组身份 chmod gs 文件/目录 sticky_bit 防火墙 firewall-cmd 开启端口 firewall-cmd --zonepublic --add-port8080/tcp --permanent 重启防火墙 systemctl restart firewalld 查看开启的所有端口 fi…

Java后端开发单元测试

测试概览 测试是用于促进鉴定软件正确性、完整性、安全性和软件质量的过程。在开发的过程中测试是必不可少的&#xff0c;测试一般分为四个阶段&#xff1a;单元测试&#xff0c;集成测试&#xff0c;系统测试&#xff0c;验收测试&#xff1b;对于后端开发人员而言&#xff0…

LAMP搭建

LAMP搭建 引子&#xff1a;本篇文章为LAMP的搭建流程&#xff0c;其中L&#xff08;Ubuntu&#xff09;、A&#xff08;Apache&#xff09;、M&#xff08;Mysql&#xff09;、P&#xff08;PHP&#xff09;。 一、L → Ubuntu Step 1&#xff1a;在Vmware Workstation中使…

LabVIEW 系统诊断

LabVIEW 系统诊断是指通过各种工具和方法检测、评估、分析和解决 LabVIEW 程序和硬件系统中可能存在的故障和性能问题。系统诊断不仅涵盖软件层面的调试与优化&#xff0c;还包括硬件交互、数据传输、实时性能等方面的检查和分析。一个成功的系统诊断能够显著提升LabVIEW应用程…

基于 GEE 提取白莲种植范围

目录 1 方法原理 1.1 步骤一 1.2 步骤二 1.3 步骤三 1.4 步骤四 2 完整代码 3 运行结果 近年来&#xff0c;随着乡村振兴战略的提出&#xff0c;我国的农业种植模式呈现出多元化的趋势。白莲具有易种植、经济效益高的特点&#xff0c;由此被广泛种植&#xff0c;本文介绍…

el-table 自定义表头颜色

第一种方法&#xff1a;计算属性 <template><div><el-table:data"formData.detail"border stripehighlight-current-row:cell-style"{ text-align: center }":header-cell-style"headerCellStyle"><el-table-column fixed…