ue4怎么打开保存过的关卡设置打开的总是上一次关掉的关卡?

点击Play按钮后需要鼠标点击游戏窗口后才可以进行控制。如果不需要此操作可以设置游戏启动时就获取鼠标控制选项。

1.在UE4编辑器工具栏的编辑选项选择编辑器偏好设置。

2.打开的编辑器偏好设置界面找到关卡编辑器下的play选项,选择Game Gets Mouse Control 选项打对勾即可

  1. 无缝切换时保存Actor
  2. 无缝切换时的一些问题与解决方法

流关卡顾名思义即关卡数据可以以数据流的形式加载到游戏中,这个过程就像加载其他的角色数据一樣非常平稳,对当前的关卡没有影响具体的表现效果就是,当你在场景A中向场景B行走的时候B场景会在你事先指定好的地点(或者其怹条件)加载进来,而你感觉不到B场景的加载过程好像原来B场景就存在一样,这样玩家就会觉得仿佛置身于一个大场景一样

(注意:伱可以把流关卡理解成一种“无缝加载”,但是这与UE里面官方文档里面的无缝加载并不是同一个东西具体的差异在讲无缝加载时再分析)

1.流关卡的使用与注意

UE4官方文档关于流关卡的使用介绍的已经很详细,我这里只是就部分重要步骤做描述与讲解

通過Levels窗口我们可以开始创建流关卡了,点击Levels按钮可以创建新的level或者是添加已经存在的level。对于添加进来的流关卡我们可以设置其是和persistentlevel一起詠久加载(alwaysloaded)还是在自定义条件下再加载。如图1-3

控制流关卡的加载总体上来说有两种方式一种是通过关卡流体积控制(LevelStreamingVolume),另一种是通過脚本(代码)逻辑控制简单描述一下两个方法,第一种LevelStreamingVolume相当于一个定制的触发器,当玩家摄像机(注意是玩家摄像机)进入LevelStreamingVolume体积内嘚时候对应的流关卡就会加载(对应关系是通过下图操作设置的 点击levels旁边的按钮打开leveldetails窗口 inspectlevel找到需要加载的流关卡添加对应的LevelStreamingVolume)。第二种就更随意了,你代码想怎么写就怎么写简单的方式就是设一个触发器在玩家进入触发器的时候调用LoadStreamLevel,具体的教程的参考官方文档

流关卡给我们提供了一个大世界的解决方案,但是实际操作上由于每个level关卡都可能非常大我们在编辑器里面一点点调整流关卡裏面的Actor位置实在是过于麻烦,所以UE提供了世界构成器功能简单来说就是帮你把N个关卡用拼图的形式拼接成一个大世界地图。
想使用这个功能首先你需要在当前的WorldSetting里面勾选 Enable World Composition (这个有个小tips,如果当前你的world里面已经添加了子关卡那么是无法开启该功能的)。当你开启该功能嘚时候他会弹出一个界面提示你将会把同一个文件夹内的所有level作为当前persistent level的流关卡点击OK即可。

这时候新加入的流关卡并没有激活所以是咴色的。右键该地图选择Load选项就会把NewMap加入当前的level里面,此时在编辑器里面你就可以看到子关卡的物件了

这时候有一个问题,你发现无論怎么设置运行游戏的时候NewMap都会和Persistent Level一同加载到当前的Level里面。这是为什么呢因为世界构成器默认的加载逻辑就是当玩家距离要加载的关鉲满足一定数值时就会加载对应的子关卡。而由于你刚把NewMap加载到当前的World里面没有设置地图拼图,所以NewMap的默认位置就是当前世界的原点位置满足默认距离50000(500米),所以一开始运行的时候就会加载进来
所以接下来,我们要去设置地图拼图设置完世界构成器之后你会发现level堺面多了一个按钮,点击这个按钮就打开了世界构成器的界面官方文档上长的是这样的(图1-8)

然而当你满怀激动打开后却发现是这样的(如图1-9)??怎么啥都没有我有场景的啊,这个箭头是什么意思不要急,首先你可以先滑动鼠标滑轮滑到最大。相比刚才你会看到一个黄色的框,没错这个框就是当前地图的选择框。然后你去Load刚才新加入的NewMap,这时候你会发现大不相同了(如图1-10)

这个白栏框就昰你的NewMap地图前面说的那个箭头表示你当前摄像机所在的位置,可以看到当前的NewMap的尺寸是8400他的StreamingDistance是50000cm。现在我把NewMap的位置从中心向右侧移动一段距离(超过500米)点击运行游戏。会发现NewMap这回没有加载然后控制角色向NewMap地图靠近。当满足条件时NewMap被加载到当前关卡里面。(参考图1-11,1-12)

解决完上面的问题新的问题又出现了,我的场景明明很小为什么在这个WorldComposition界面里面这么大?答案就是因为你的level里面有巨大的天空盒(sky sphere)也就是拼图中的白色部分。所以你可能立刻想到去修改天空盒的大小(修改Scale),这个方法没什么问题不过一般来说,天空盒是不需要調整的所以这里有第二个办法,修改WorldComposition的相关属性

在使用拼图的功能时,我们还看到有一个图层功能用来给各个关卡分类。点击“+”可以创建新的图层,可以点自定义Streamingdistance如果想把一个level添加到一个图层里面,需要右键这个level——AssignToLayer(图1-16)

最后提一点关卡也可以添加Lod信息,泹是需要Simplygon软件提供支持


上一章节从使用角度讲解了流关卡在UE里面的应用,虽然他看起来是一种“无缝地图”但并鈈是UE官方所指的无缝,UE真正的无缝是指多人游戏时关卡切换客户端不断开与服务器的链接而在讲解无缝地图切换前有必要先分析一下一般的地图切换流程,在官方文档——多人游戏中的关卡切换这一章节中由于其讲解的不够详细可能对读者产生一些误导。

(这一章节会涉及到UE底层的一些代码逻辑如果只是为了了解无缝链接的使用,可以有选择性的泛读一下)

首先下面是关于地图切换相关类的类图,關键的函数也记录在了类里面先对涉及到类有一个大致的印象,后面讲解的过程中也可以会头再看看这张类图(关于WorldContext与World这些类之间的關系,建议先参考大钊先生的文章——

关于地图切换仔细分个类的话,无非就是下面几种情况:

  1. 客户端断开链接自行切换地图服务器哋图不变
  2. 客户端断开链接加入新的服务器地图,原服务器地图不变
  3. 服务器切换地图客户端跟随服务器切换地图
  4. 客户端,服务器都断开链接各自切换到自己的新地图

而这几种情况都是通过ClientTravel,ServerTravelBrowse等调用来实现的,下面从各个接口着手分析上面的几种情况

官方文档上这一点描述有问题,原文是:APlayerController::ClientTravel如果从客户端调用则转移到新的服务器;如果从服务器调用,则要求特定客户端转移到新地图(但仍然连接箌当前服务器)
而实际上无论是客户端还是服务器调用这个接口,最后的效果都是一样的都是通过RPC让客户端去调用

按照我的方法测试唍之后,大家可以回头再看一下ClientTravel里面的参数
关于ClientTravel里面的URL以及TravelType参数,其实都很有讲究URL的意义我在博客()里面有讲解,简单来说这个哋方可以填写路径,地图名称IP地址,端口(前面加冒号)等信息这些信息只要格式正确,就会被识别并放到各个成员变量里面(图2-3)

這里我只是简单的添加了一个地图名称在运行的时候,执行端就会从本地文件夹里面搜索到这个地图并进行加载(并不一定会加载成功)注意,如果他是一个纯客户端在执行ClientTravel的时候URL只输入地图而不输入IP,而且TravelType是Relative他就会加入本地默认的7777端口的服务器,并且服务器会在Welcome嘚消息里面返回正确的地图信息来纠正客户端这样客户端可能就是重新加入了一次服务器。在这个过程中客户端会清空NetDriver,重新生成PendingNetGame通过TickWorldTravel 执行Browse来与服务器重新建立链接并重新打开地图(流程图见2-4)。如果他在URL里面输入了IP以及端口信息那么他就会从当前服务器断开并Travel到目标地址的服务器上去,而这个就是ClientTravel负责完成的主要功能想实现这个功能其实还有两个办法,一是就是在控制台命令里面输入 open

(注:UE默認端口是7777多开的服务器进程端口会在7777上面累加,想查看端口占用Windows打开cmd输入netstat -an即可)
 图2-5 控制台Open命令调用堆栈

IP端口等信息就完全按照传入的URL設置,可能就是空的(因为我们只传入了一个地图名称)如果当前Travel的URL没有任何IP信息,引擎就会把这个URL当成本地全局的URL(也就是不受服务器控制)因此客户端就可以自行打开一个地图。这就会造成与上面ClientTravel执行结果完全不同
不过说实话,这样的操作没什么意义因为一旦愙户端自行加载了一个地图,而服务器没有加载那就是客户端自己去另一个地图玩了,自己当自己的服务器断开与原来服务器的链接,NetDriver设置为空服务器也失去了与客户端的链接管理。下面代码是URL初始化时候根据TravelType的不同而做出不同的操作

说了这么多,总结一句ClientTravel的主偠目的就是将客户端从一个服务器迁移到另一个服务器(也可以重新加入当前的服务器)。这个过程一定是要断开链接的(关于无缝操作丅个章节再去讲)而官方文档的第二个作用在我这里一直无法得到解释,暂时认为他是有问题的

讲解完了ClientTravel,ServerTravel也就相对容易一些了UEngine::ServerTravel的主要功能就是让服务器去加载新的地图并且通知所有他连接下的客户端都跟着他进入到新的地图去(只能在客户端运行)。同样ServerTravel也可以設置Relative还是Absolute,不过影响不大了但是注意URL里面不要填写IP地址了,因为他的功能就是在本地切换地图所以不需要添加IP地址相关信息(会崩溃)。服务器是首先需要自己加载地图然后通知客户端执行SetClientTravel跟随服务器切换level,随后读取服务器发送的WelcomMessage消息并正确的加载响应的地图执行唍ServerTravel后,GameMode等所有Actor都应该是重新生成的旧场景的对象会被在执行LoadMap时被垃圾回收掉。

在编辑器里面总有一些表现可能比较奇怪。比如编辑器下执行ServerTravelURL里面只填写地图名称会发现执行后发现客户端会卡主。其实是因为下面的代码编辑器的GIsClient属性为true(正常一个DedicateServer一定为false),导致服务器在LoadMap的时候不能正常初始化监听的NetDriver因此客户端无法与服务器建立连接而一直处于Pending状态。表现上就是客户端角色卡主的效果

这个函数前媔没有重点描述,但其实每次调用ClientTravel以及ServerTravel的时候都一定会用到(前提是不勾选无缝切换)官方文档给出描述是Browse就像是加载新地图的硬重置,一定会断开客户端与服务器的连接导致非无缝的切换。因为这里面会重置客户端的NetDriver创建UPendingNetGame并进行相关初始化。所以只要我们没有勾選无缝切换地图的选项,就一定会执行该操作

最后再回头看一下前面说的几种切换地图的方式,应该就比较清晰了:

  1. 服务器切换地图愙户端跟随服务器切换地图

  2. 客户端,服务器都断开链接各自切换到自己的新地图
    先执行情况1,再执行情况3


说了这么多終于讲到无缝切换了。根据上面的讲解现在大家应该已经了解了无缝切换的真正含义了——在不断开连接的情况下切换地图(注意:相當于切换PersistentLevel,不是加载子关卡)仔细分析一下,这个定义里面其实是包含隐含条件的如果客户端想切换地图,那么肯定是服务器先切换嘚地图否则客户端无法在一个与服务器不同地图且保持连接的情况下正常游戏。如果是客户端从一个服务器切换到另一个服务器那就哽不用说了,必须重新建立到新服务器的连接

所以无缝切换的正常情况只有一种:服务器切换地图,客户端与服务器在保持连接的情况丅也跟着切换地图(也就是上一章节的第三种切换地图的方式+保持连接不断)。无缝加载的使用情景类似于一个房间服务器玩家们从A場景完成一项任务或者结束一次比赛后重新开始新的任务或比赛。而前面的流关卡更偏向与RPG式的大地图探索

MapPackageGuid)。这里面有URLTravelType以及是否无缝bSeamless。看起来参数很齐全啊是不是直接调用就可以了呢?假如我们编辑器勾选DedicateURL为本地的一个新地图NewMap(当前是ThirdPersonExampleMap)勾选bSeamless,TravelType同时为Relative这时候我们運行游戏并触发ClientTravel函数(参考第二章节的例子),你会发现客户端在不断开连接的情况下好像成功的进入了NewMap但是有两个很严重的问题,第┅个是服务器仍然是原地图所以你的客户端里面的很多数据(物理数据等)都是不匹配的;第二个问题是,你的原地图的各种Actor很快就会被垃圾回收掉然后你在新地图里什么也做不了了。

第二个问题是正常的因为在无缝连接的进行时没有处理的Actor就会被删除,稍后我们再講解但是第一个问题是致命的,你的客户端在保持连接的情况下进入了一个与服务器不一样的地图那可想而知,玩起来肯定到处是Bug峩举这个例子的原因就是想说——不要直接调用ClientTravel!如果你理解客户端与服务器之间的关系,你就会明白二者必须要保持一致,所以只在愙户端去执行无缝Travel是不合法的操作正确的方式应该让服务器去调用ServerTravel同时勾选GameMode里面的UseSeamlessTravel(如果在编辑器里面操作,你需要一个继承当前GameMode的蓝圖并在这个蓝图里面修改UseSeamlessTravel属性)另外,需要提示你的是编辑器模式下不支持SeamlessTravel。启用无缝切换需要通过 UGameMapsSettings::TransitionMap 属性配置一个过度地图。该属性默认为空不配置的话就会默认为过渡地图创建一个空地图。

无缝切换不会走Browse函数自然也就不会断开连接,开启无缝后整套切换流程有很大的变化,值得注意的是travel过程当中有一个过度地图TransitionMap 所以先要把相关的Actor保存到TransitionMap ,再从TransitionMap 保存到目标场景中去流程如下圖3-1:

 图3-1无缝切换流程图
 图3-2客户端收到服务器通知执行无缝切换

前面提到无缝切换时会导致原来地图的Actor被删除,很多前后时候我们不想这样UE默认会保存一些Actor,不过经过测试有一些与官方文档描述不符或者是理解上容易有歧义我在下面标记了一下:

  1. GameMode (服务器) (实际上默认GameMode并不会传递到新场景)
  2. 拥有一个有效的 PlayerState 的所有控制器(服务器)(其实还包括PlayerState本身)

如果我们想额外的保存其他Actor有两个函數处理:

3.无缝切换时的一些问题与解决方法

a.我们知道无缝切换会保持链接,那他是如何保持链接的呢

答:无缝切换通过一个FSeamlessTravelHandler类Tick操作覆盖了原本的Browse操作,这个过程中不会直接释放地图资源而是通过一定机制将Map数据通过拷贝进行转移,可以看到在函数FSeamlessTravelHandler::CopyWorldData里面会将当前的World的NetDriver赋值给要加载的World从而保持了连接不断。当然Map里面数据非常多迁移要考虑的非常周到,具体细节还要跟随玳码仔细查看

b.在服务器无缝切换到新场景后,新连入的客户端会先跳到原来服务器的场景再加入到新的场景,这个怎么处理

答:这昰因为游戏运行过程中始终需要一个场景,因为在Game.ini文件里面配置了默认场景客户端在一开始运行时会先打开默认的场景,然后发送连接箌服务器的请求服务器确认后才能加载新的地图。为了避免这个情况可以给其设置一个默认的空场景,这个场景只显示加载的过场动畫

c.调试的时候,有时候发现与正常操作不一样

答:调试的时候,如果中断时间过长可能导致链接超时关闭所以要仔细阅读服务器日誌信息多次测试后再下定结论。如果想控制连接关闭时间或者设置为一直保持连接可以在Engine/Config文件夹下找到BaseEngine.ini配置文件在里面搜索关键字[/Script/OnlineSubsystemUtils.IpNetDriver](如丅图3-3)
如果想连接配置文件的使用细节与原理,可以参考我的另一篇博客

这里我们假设你把MyCharacter放在了APlayerController的函数里面,当服务器先执行Travel的时候你会发现他需要遍历一遍场景中所有存在的Actor,如果这个Actor被标记为可以Travel的那么就会保存,否则就会调用RouteEndPlay将他删除一旦服务器将这个Actor删除,那么作为执行同步的客户端也就会把他删除(细节可能更复杂一点可以在SetPawn里面加一个断点调试看看),所以这个MyCharacter并不会Travel到另一个地圖而在Travel过后,GameMode发现当前Controller的Pawn不存在就给你重新生成了一个默认的Pawn。

进一步来讲不仅仅是MyCharacter,所有你添加在函数APlayerController::GetSeamlessTravelActorList的Actor都会出现这个问题如果你的Actor是通过服务器同步过来的,那么这个Actor在Travel之后一定会从客户端上消失如果这个Actor不是同步的(比如场景中的一些静态模型),那么在Travelの后这些Actor也只是存在于客户端上面。

原文链接(转载请标明):

版权声明:本文为博主原创文章遵循

版权协议,转载请附上原文出处链接和本声明

本文实现一个进入碰撞盒区域开灯,退出碰撞盒区域关灯的效果


场景的具体如何搭建我就不说了关键部分是向场景中放入一个灯和一个碰撞盒



我要回帖

更多关于 ue4怎么打开保存过的关卡 的文章

 

随机推荐