MMO地图传送

news2024/9/21 19:51:53

本篇由以下四个点讲解:

创建传送点

传送点配置

编辑器扩展:传送点数据生成

传送协议与实现

创建传送点

建碰撞器触发

//位置归零

建一个传送门cube放到要传送的位置(这个teleporter1是传出的区域

这是从另一张地图传入时的传送门

创建一个脚本TeleporterObject给每个传送cube都绑上脚本

通过脚本,让传送门在编辑器下面还能绘制出来

给每个传送点编号

把特效挂在传送点上

//把野外场景的传送也加上(并把传送门的id改了

碰撞检测

TelePorterObject:OnTriggerEnter

private void OnTriggerEnter(Collider other)
{
    PlayerInputController playerInputController=other.GetComponent<PlayerInputController>();
    //传入的对象是否有玩家控制器
    if(playerInputController!=null&&playerInputController.isActiveAndEnabled)
    {
        //得到传送点的ID
        TeleporterDefine teleDefine = DataManager.Instance.Teleporters[this.ID];
        if(teleDefine==null)
        {
            //从角儿控制器取得角色character,第几个传送点
            Debug.LogErrorFormat("TeleporterObject: Character [{0}] Enter Teleporter [{1}] ,But TeleporterDefine not existed", playerInputController.character.Info.Name, this.ID);
            return;
        }
        Debug.LogFormat("TeleporterObject: Character[{0}] Enter Telepoter [{1}:{2}] ",playerInputController.character.Info.Name, teleDefine.ID,teleDefine.Name); ;
        if(teleDefine.LinkTo>0)
        {
            if(DataManager.Instance.Teleporters.ContainsKey(teleDefine.LinkTo))
                MapService.Instance.SendMapTeleporter(this.ID);
            else Debug.LogErrorFormat("Teleporter ID:{0} LinkID {1} error!",teleDefine.ID,teleDefine.LinkTo);   
        }
    }
}

在MapService中发送进入传送点的信息SendMapTeleporter

SendMapTeleporter
public void SendMapTeleport(int teleporterID)
{
    Debug.LogFormat("MapTeleporterRequest :teleporterID:{0}", teleporterID);
    NetMessage message = new NetMessage();
    message.Request = new NetMessageRequest();
    message.Request.mapTeleport = new MapTeleportRequest();
    message.Request.mapTeleport.teleporterId = teleporterID;
    NetClient.Instance.SendMessage(message);
}

向客户端发送有角色进入传送点的信息

message MapTeleportRequest
{
	int32 teleporterId = 1;
}

只需要传一个传送点id即可(也可以传地图的id,再传送点的id)

 服务端的协议处理MapService:OnMapTeleport

在MapService()中, 

订阅:

     MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<MapTeleportRequest>(this.OnMapTeleport);

void OnMapTeleport(NetConnection<NetSession> sender,MapTeleportRequest request)
{
    //得到客户端进行传送点传送的对象
    Character character=sender.Session.Character;
    Log.InfoFormat("OnMapTeleporter: characterID:{0}:{1} TeleporterId:{2}", character.Id, character.Data, request.teleporterId);

    //没有该传送点
    if(!DataManager.Instance.Teleporters.ContainsKey(request.teleporterId))
    {
        Log.WarningFormat("Source TeleporterID[{0}] not existed", request.teleporterId);
        return;
    }
    

    TeleporterDefine teleportDefine=DataManager.Instance.Teleporters[request.teleporterId]; 
    if(teleportDefine.LinkTo==0||!DataManager.Instance.Teleporters.ContainsKey(teleportDefine.LinkTo))
    {
        Log.WarningFormat("Source TeleporterID [{0}] LinkTo ID [{1}] not existed", request.teleporterId, teleportDefine.LinkTo);
    }

    //从客户端传过来的传送点数据表teleportDefine.LinkTo:6 
    //取的key为6 传送目标点
    TeleporterDefine teleporterDefine1 = DataManager.Instance.Teleporters[teleportDefine.LinkTo];

    //角色所在的地图,角色离开处理
    MapManager.Instance[teleportDefine.MapID].CharacterLeave(character);
    //把新位置信息填充给角色
    character.Position=teleporterDefine1.Position;
    character.Direction=teleporterDefine1.Direction;
    //角色进入新地图
    MapManager.Instance[teleporterDefine1.MapID].CharacterEnter(sender,character);
}

关于传送点配置表TeleporterDefine:

点击这里查看是否有TeleporterDefine配置表生成

扩展编辑器

MapTool:遍历所有传送点,把里面的世界坐标转换成逻辑坐标存到配置表中

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEditor;
using Common.Data;
public class MapTool : MonoBehaviour
{
    [MenuItem("Map Tools/Export Teleportters")]
    //扩展功能:static
    public static void ExportTeleporters()
    {
        DataManager.Instance.Load();

        Scene current=EditorSceneManager.GetActiveScene();
        string currentScene=current.name;
        //把当前场景记录下来,并检查有无保存
        if(current.isDirty)
        {
            EditorUtility.DisplayDialog("提示", "请先保存当前场景", "确定");
            return;
        }

        List<TeleporterObject> allTeleporters=new List<TeleporterObject>();

        foreach(var map in DataManager.Instance.Maps)
        {//根据地图里配置名字生成原始路径
            string sceneFile = "Assets/Levels/" + map.Value.Resource + ".unity";
            if(!System.IO.File.Exists(sceneFile))
            {//判断每一个场景文件是否存在
                Debug.LogWarningFormat("Scene {0} not existed!", sceneFile);
                continue;
            }
            //打开单个场景
            EditorSceneManager.OpenScene(sceneFile,OpenSceneMode.Single);

            //检查所有的传送点
            TeleporterObject[] teleporters=GameObject.FindObjectsOfType<TeleporterObject>();    
            foreach(var teleporter in teleporters)
            {
                Debug.Log("传送点ID" + teleporter.ID);
                if(!DataManager.Instance.Teleporters.ContainsKey(teleporter.ID))
                {//检查传送点的id在配置表中是否存在
                    EditorUtility.DisplayDialog("错误", string.Format("地图:{0} 中配置的 Teleporter:[{1}]中不存在", map.Value.Resource, teleporter.ID), "确定");
                    return;
                }

                TeleporterDefine def=DataManager.Instance.Teleporters[teleporter.ID];
                if (def.MapID != map.Value.ID)
                {//地图配的mapID是否正确
                    EditorUtility.DisplayDialog("错误", string.Format("地图:{0} 中的配置的Teleporter:[{1}] MapID:{2} 错误", map.Value.Resource,teleporter.ID,def.MapID), "确定");
                    return;
                }
                def.Position=GameObjectTool.WorldToLogicN(teleporter.transform.position);
                def.Direction=GameObjectTool.WorldToLogicN(teleporter.transform.forward);
            }
        }
        //Save逻辑写在DataMangaer下,运行时是不会受影响的
        DataManager.Instance.SaveTeleporters();
        EditorSceneManager.OpenScene("Assets/Levels/" + currentScene + ".unity");
        EditorUtility.DisplayDialog("提示", "传送点导出完成", "确定");
    }
    
}

把所有传送点的layer改成teleporter;因为角色是Default;Default之间是不可能碰撞的

演示:

传送成功;

 传送请求:1号传送点传送到野外的6号点

//从野外传回主城

5号传送点,传LinkTo2号传送点

//但是在野外的相机没有对着角色;在两个场景的切换时,角色会浮空

//Add:可以在场景切换时做一个Loading进度条掩盖

->Map01只有MainPlayerCamera带过来的相机发挥跟随角色的作用/创建角色时相机已经挂上了

关于到了新的场景中固定UI没有显示

把UIMainCity做成单例

(在加载新场景时UIMainCity会再创建实例

//可以看到现在加载到另一个场景,显示了UIMainCity和MainPlayerCamera以及UIWorldElementManager等;还有一些在每个场景中必要的GameObject:

//它们都是挂了单例脚本的物体

//关于刷新数据

例如小地图的mapImage

//小地图需要在次世界场景下加一个BoundingBox;根据当前角色的位置更新在小地图上的位置

需要将每次切换场景时把角色数据都拉一次进来

在UIMinmap.cs中,只有在启动时才加载了小地图

//在后面的文章会讲到

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql笔记—基础

1.SQL语句 DDL&#xff08;数据库对象操作&#xff09;、DML&#xff08;增删改&#xff09;、DQL&#xff08;查询&#xff09;、DCL&#xff08;用户和权限操作&#xff09; 2.DDL&#xff1a; 1.数据库操作&#xff1a; show databases; create database []; use []; sele…

网络工程师学习笔记——无线通信网

移动通信 从1G到3G都是针对语音通话设计的&#xff0c;只有4&#xff27;才可以与Internet衔接 1978年美国贝尔实验室开发了高级移动电话系统&#xff08;AMPS&#xff09;&#xff0c;可以随时随地的进行通信&#xff0c;采用蜂窝技术解决了公用通信系统所面临的大容量要求和…

初识Linux · 进度条

目录 前言&#xff1a; 1 缓冲区和回车换行 2 进度条 前言&#xff1a; 我们目前学习了些许知识&#xff0c;已经足够支持我们写一个非常非常小的项目了&#xff0c;即进度条&#xff0c;相信大家都有过下载游戏&#xff0c;等待游戏更新完成的时候&#xff0c;那么此时就有…

电器维修系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;客服聊天管理&#xff0c;基础数据管理&#xff0c;公告管理&#xff0c;新闻信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;新闻信息&#xff0c;我的 开发系…

站长工具 API 接口,助力网站管理新高度

站长工具是一款非常实用的网站管理工具&#xff0c;通过其提供的API接口&#xff0c;可以轻松实现多种功能&#xff0c;如域名反查、域名备案查询、IPV6归属地查询等。这些功能可以帮助网站管理员更好地管理和优化自己的网站。以下是简单的代码示例&#xff0c;展示了如何使用站…

康姿百德公司官网柔压磁性枕豪华款高科技邂逅温柔夜活力满满!

康姿百德豪华柔压磁性枕慢回弹拥抱每寸肌肤&#xff0c;科技面料让呼吸自由夜夜好眠不是梦&#xff01; 现代家居设计不仅注重美观&#xff0c;更强调功能性和舒适性。康姿百德柔压磁性枕&#xff08;豪华款&#xff09;通过将高科技材料与创新设计结合&#xff0c;为我们的家…

Java反序列化漏洞-TemplatesImpl利用链分析

文章目录 一、前言二、正文1. 寻找利用链2. 构造POC2.1 生成字节码2.2 加载字节码1&#xff09;getTransletInstance2&#xff09;defineTransletClasses 2.3 创建实例 3. 完整POC 三、参考文章 一、前言 java.lang.ClassLoader#defineClass defineClass可以加载字节码&…

最大N个数与最小N个数的和

题目描述 给定一个数组&#xff0c;编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重 说明: 数组中数字范围[0&#xff0c;1000]最大N个数与最小N个数不能有重叠&#xff0c;如有重&#xff0c;输入非法返回-1输入非法返回-1 输入描述 第一行输入M&a…

uboot:配置编译

了解BSP 在嵌入式系统中&#xff0c;BSP&#xff08;Board Support Package&#xff09;被称为板级支持包或板级支持软件。它是一组针对特定硬件平台的软件支持包&#xff0c;为开发人员提供了一个统一的接口层&#xff0c;简化了硬件和软件之间的交互。BSP的主要功能和特点如…

Python数据分析-绘制图表

示例1&#xff1a; from pyecharts.charts import Bar # 柱状图 from pyecharts import options as optsfrom pyecharts.render import make_snapshotbar Bar() bar.add_xaxis([一月, 二月, 三月, 四月, 五月]) bar.add_yaxis("销售额", [10, 20, 15, 25, 30])# 配…

spring 事物使用场景说明

事务使用场景。 在某些业务场景下&#xff0c;如果一个请求中&#xff0c;需要同时写入多张表的数据。为了保证操作的原子性&#xff08;要么同时成功&#xff0c;要么同时失败&#xff09;&#xff0c;避免数据不一致的情况&#xff0c;我们一般都会用到spring事务。 确实&am…

使用Node-API进行异步任务开发

一、Node-API异步任务机制概述 Node-API异步任务开发主要用于执行耗时操作的场景中使用&#xff0c;以避免阻塞主线程&#xff0c;确保应用程序的性能和响应效率。 1、应用场景&#xff1a; 文件操作&#xff1a;读取大型文件或执行复杂的文件操作时&#xff0c;可以使用异步工…

TCP远程命令执行

目录 一. 命令集 二. 命令执行模块实现 三. 服务端模块实现 四. 服务端调用模块实现 五. 客户端模块实现 六. 效果展示 此篇教大家如何利用TCP进行远程命令执行。 一. 命令集 将值得信任的命令放进一个txt文件中&#xff0c;执行命令时&#xff0c;就去这…

英语每日一段 195

Promising economic indicators won’t instantly reverse the lingering impact of hard times for millions of families, workplace culture expert Jessica Kriegel said. “Perception and reality are sometimes aligned and sometimes not,” Kriegel told Newsweek. “…

这才是程序猿梦想的终端,赶快动手搞起来

文章目录 目标资源列表安装iTerm2安装oh-my-zsh安装颜色主题查找配置文件将配置内容复制到本地设置iTerm2 安装NERD FONTS下载字体安装设置iTerm2 安装PowerLevel10k修改.zshrc重新加载配置 安装插件下载[语法高亮](#syntaxhighlighting)下载[命令提示](#autosuggestions)配置插…

git的使用和gdb工具

1.git的使用 首先现在gitee上新建一个仓库 然后复制克隆链接到本地仓库 在本地仓库中&#xff0c;我们可以用git status查看仓库状态 我们要提交代码就是要三步 git add 文件名 git commit -m "写提交的日志" git push 将代码上传到远端仓库 然后你就完成一次提…

AIOT人工智能物联网六大场景

AIOT&#xff08;人工智能物联网&#xff09;融合了人工智能技术和物联网技术&#xff0c;实现了设备之间的智能互联和数据交互&#xff0c;在多个场景中都有广泛的应用。以下是一些主要的AIOT场景&#xff1a; 一、智能交通 智能汽车&#xff1a; 自动驾驶是AIOT在智能交通领…

tolower/toupper 函数讲解

目录 1.函数介绍 2.示例如下&#xff1a; 方源一把抓住VS2022&#xff0c;又是顷刻炼化&#xff01;&#xff1f; 1.函数介绍 C语言中提供了两种函数用于字符大小的转换 tolower可以将大写字符转小写字符&#xff0c;toupper可以将小写字符转大写字符 tolower函数与touppe…

设计并用Java实现一个简易的规则引擎

文章目录 前言正文一、代码结构二、核心代码2.1 上下文数据接口 ContextData.java2.2 规则接口 Rule.java2.3 规则引擎接口 RuleEngine.java2.4 规则引擎上下文类 RuleEngineContext.java2.5 规则引擎默认实现类 DefaultRuleEngine.java2.6 执行时出错监听器接口 ExecuteOnErro…

[mysql]SQL语言的规则和规范

规则 是什么呢&#xff0c;规则就是我们最基本&#xff0c;每时每刻都要遵守的比如人行道靠右&#xff0c;不能逆行&#xff0c; 规范 呢就是锦上添花&#xff0c;如果你不这么做&#xff0c;是不那么道德&#xff0c;不那么好的&#xff0c;就像小学生见到老师要问好&#…