【UE】大世界子关卡StreamingLevel加载流程

news2024/11/16 13:55:42

受限于硬件,当项目需要制作大世界的时候,整张大地图无法也没必要全部加载进内存。和所有支持大世界的引擎一样,UE采取了分块加载的方式:除了一个持久关卡(PersistentLevel)的加载以外,采用的都是运行时动态加载的方式,我们称这些关卡为子关卡或者流关卡(StreamingLevel)。当玩家到达子关卡边界的时候它们才开始加载。

本文基于UE4.27,简述流关卡加载的流程和时机。

文章目录

  • 流关卡加载涉及到的类
  • 加载流程
    • 收集流关卡资源
    • 根据玩家位置计算Tiles的可见性
    • 执行流关卡加载
  • 应用:屏蔽部分子关卡的加载

流关卡加载涉及到的类

一个大世界(World)由多个关卡(Level)组成,其中与流关卡加载有关的关键类及其属性如下:
在这里插入图片描述
ULevelStreaming:存放与流关卡加载相关的标记和方法,如当前状态(加载中、已加载、加载但不可见、加载且可见…)、目标状态等。

UWorldComposition:加载流关卡的主要负责类,其中Tiles存放其所属World的子关卡Summary信息,是流关卡加载的最小单位,TilesStreaming存放其当前状态。两个TArray通过下标一一对应。这两个数据结构基本只在开始的时候初始化一次,存储所属World下所有的流关卡信息。

UWorld:StreamingLevelsToConsider存放当前待加载的流关卡,StreamingLevels存放已经加载的流关卡。属于运行时动态更新的两个容器

加载流程

加载流程分为三个部分:

  1. 收集关卡资源
  2. 根据玩家位置标记流关卡状态
  3. 执行关卡的加载or卸载
    在这里插入图片描述

收集流关卡资源

在UWorldComposition构造即将完成的时候,会调用UWorldComposition::Rescan进行流关卡资源的收集。这个函数会查找当前World的根目录,将其中流关卡的Summary信息反序列化到内存。
在这里插入图片描述
注意这里只是反序列化了各个关卡的一点必要信息如关卡位置,给后续判断关卡什么时候应该加载用。并没有把整个流关卡都反序列化进来。

收集完信息到Tiles这个结构体以后,调用UWorldComposition::PopulateStreamingLevels给每个流关卡都赋上初始状态。

这一步的结果就是完成了流关卡信息的收集,具体到结构体就是Tiles和TilesStreaming的初始化。

这一步骤基本只在构造即将结束的时候执行一次。接下来的两个步骤是在游戏进行中反复执行的。

根据玩家位置计算Tiles的可见性

UWorld::Tick()会调用到UWorldComposition::UpdateStreamingState这里根据一些必须加载的位置如玩家当前位置、PersistentLevel的位置计算应该加载、卸载的关卡。
在这里插入图片描述
这一步也只是做了关卡状态的计算,标记了关卡的TargetState,并将待加载的关卡放入UWorld的StreamingLevelsToConsider容器中。并没有真正加载关卡

执行流关卡加载

终于到了真正加载的地方了。客户端绘制到屏幕的时候 根据上一步收集来的StreamingLevelsToConsider进行关卡的载入内存和显示。
在这里插入图片描述实际的加载在ULevelStreaming::RequestLevel中进行:

bool ULevelStreaming::RequestLevel(UWorld* PersistentWorld, bool bAllowLevelLoadRequests, EReqLevelBlock BlockPolicy)
{
	... ...
	const FName DesiredPackageName = bIsGameWorld ? GetLODPackageName() : GetWorldAssetPackageFName();
	if (bAllowLevelLoadRequests)
	{
		const FName DesiredPackageNameToLoad = bIsGameWorld ? GetLODPackageNameToLoad() : PackageNameToLoad;
		const FString PackageNameToLoadFrom = DesiredPackageNameToLoad != NAME_None ? DesiredPackageNameToLoad.ToString() : DesiredPackageName.ToString();
		if (FPackageName::DoesPackageExist(PackageNameToLoadFrom))
		{
		... ...
			LoadPackageAsync(DesiredPackageName.ToString(), nullptr, *PackageNameToLoadFrom, FLoadPackageAsyncDelegate::CreateUObject(this, &ULevelStreaming::AsyncLevelLoadComplete), PackageFlags, PIEInstanceID, GetPriority());
		... ...
	}
	... ...
}

应用:屏蔽部分子关卡的加载

如果本地有子关卡资源,但运行时不希望加载,需要进行子关卡的屏蔽。在UWorldComposition::Rescan收集的时候对指定关卡进行屏蔽即可。

注意由于子关卡的信息收集和加载是在Server和Client各自进行的,并不是通过网络同步从Server下发到Client。如果要做屏蔽操作也是服务器和客户端都需要执行的。

否则会出现服务器屏蔽了地表但客户端仍会显示,而由于碰撞的裁决在服务器,这块地表会没有碰撞:

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

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

相关文章

网络通信快速入门

🏡个人主页 : 守夜人st 🚀系列专栏:Java …持续更新中敬请关注… 🙉博主简介:软件工程专业,在校学生,写博客是为了总结回顾一些所学知识点 目录网络编程实现网络编程的三要素&#x…

少儿编程 电子学会图形化编程等级考试Scratch一级真题解析(选择题)2022年12月

少儿编程 电子学会图形化编程等级考试Scratch一级真题解析2022年12月 选择题(共25题,每题2分,共50分) 1、小明想在开始表演之前向大家问好并做自我介绍,应运行下列哪个程序 A、 B、 C、 D、 答案:D

【MySQL】第17章_触发器

第17章_触发器 在实际开发中,我们经常会遇到这样的情况:有 2 个或者多个相互关联的表,如商品信息和库存信息分别存放在 2 个不同的数据表中,我们在添加一条新商品记录的时候,为了保证数据的完整性,必须同时…

Linux - 内存性能评估

文章目录概述free 命令指定的时间段内不间断地监控内存的使用情况通过watch与free相结合动态监控内存状况vmstat命令监控内存“sar –r”命令组合小结概述 内存的管理和优化是系统性能优化的一个重要部分,内存资源的充足与否直接影响应用系统的使用性能。在进行内存…

C语言-基础了解-07-C运算符

c运算符 一、算术运算符 假设变量 A 的值为 10&#xff0c;变量 B 的值为 20&#xff0c;则&#xff1a; 实例 #include <stdio.h>int main() {int a 21;int b 10;int c ;c a b;printf("Line 1 - c 的值是 %d\n", c );c a - b;printf("Line 2 - …

机器学习100天(四十一):041 对偶支持向量机-公式推导

《机器学习100天》完整目录:目录 机器学习 100 天,今天讲的是:对偶支持向量机-公式推导! 本节主要延续上一节的内容,推导线性支持向量机的对偶形式。本节内容包含的数学理论和推导很多,我尽量简化其中的数学部分,只做感性的介绍,便于大家在理解的同时不受数学复杂公式…

ubuntu 18.04 虚拟机分区扩容

我的虚拟机存在一个问题&#xff0c;原来分配的是60G的空间&#xff0c;但实际只用了30G就已经最显示空间已经满&#xff0c;没办法使用:通过fdisk -l查看分区情况查看LVM卷组的信息Free PE / Size 7551 / <29..50 GiB&#xff0c;这是还可以扩充的大小#lvextend -L 10G /de…

git常用命令汇总

Git 是一种分布式版本控制系统&#xff0c;它具有以下优点&#xff1a; 分布式&#xff1a;每个开发者都可以拥有自己的本地代码仓库&#xff0c;不需要连接到中央服务器&#xff0c;这样可以避免单点故障和网络延迟等问题。 非线性开发&#xff1a;Git 可以支持多个分支并行开…

踩坑:解决npm版本升级报错,无法安装node-sass的问题

npm版本由于经常更新&#xff0c;迁移前端项目时经常发现报错安装不上。 比如&#xff0c;项目经常使用的sass模块&#xff0c;可能迁移的时候就发现安装不了。 因为node-sass 编译器是通过 C 实现的。在 Node.js 中&#xff0c;采用 gyp 构建工具进行构建 C 代码&#xff0c…

自制有声书阅读器:用PaddleSpeech打开读书新方式

吕声辉&#xff0c;飞桨开发者技术专家&#xff08;PPDE&#xff09;&#xff0c;某网络科技公司研发工程师。主要研究方向为图像识别&#xff0c;自然语言处理等。 • AI Studio主页 https://aistudio.baidu.com/aistudio/personalcenter/thirdview/227158 项目背景 随着互联…

第十四届蓝桥杯三月真题刷题训练——第 3 天

目录 题目1&#xff1a;门牌制作 题目描述 运行限制 代码&#xff1a; 题目2&#xff1a;货物摆放_long 题目描述 答案提交 运行限制 代码&#xff1a; 题目3&#xff1a;跳跃_dp 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码&#xff1a; 题目4&a…

AAAI顶会行人重识别算法详解——Relation Network for Person Re-identification

1.论文整体框架概述 在行人重识别任务中,通常都是对整个输入数据进行特征提取,但是缺少了局部信息。能不能既考虑局部与整体信息,也同时加入他们的联系呢?这篇论文主要的思想就是局部信息和全局信息的融合。 整体流程如上图所示, 首先对整体进行特征提取, 通常采用…

【FPGA】Verilog:MSI/LSI 组合电路之解码器 | 多路分解器

写在前面&#xff1a;本章将理解编码器与解码器、多路复用器与多路分解器的概念&#xff0c;通过使用 Verilog 实现多样的解码器与多路分解器&#xff0c;通过 FPGA 并使用 Verilog 实现。 Ⅰ. 前置知识 0x00 解码器与编码器&#xff08;Decoder / Encoder&#xff09; 解码器…

素数分类的猜想==素数,划分分类,就分为真素质数与非真素质数

素数分类的猜想 根据哥德巴赫公理&#xff08;我暂不称之为猜想了&#xff09;&#xff0c;普通素数加一&#xff0c;成为合数&#xff0c;必可分解成两个素数&#xff0c;所以&#xff0c;两个素数Pi,Pj相加减一&#xff0c;是有可能为素数Pn的&#xff0c;这样的素数Pi,Pj&am…

扩散模型DDPM开源代码的剖析【对应公式与作者给的开源项目,diffusion model】

扩散模型DDPM开源代码的剖析【对应公式与作者给的开源项目&#xff0c;diffusion model】一、简介二、扩散过程&#xff1a;输入是x_0和时刻num_steps&#xff0c;输出是x_t三、逆扩散过程&#xff1a;输入x_t&#xff0c;不断采样最终输出x_0四、具体参考算法流程图五、模型mo…

Android Framework 启动流程必知必会

课前预习在了解启动流程之前先了解一下下面两个概念:1、子进程与父进程的区别1.除了文件锁以外,其他的锁都会被继承2.各自的进程ID和父进程ID不同3.子进程的未决告警被清除4.子进程的未决信号集设置为空集2、什么是写时拷贝(copy-on-write)Linux 的 fork() 使用是通过「写时拷贝…

【Linux】Linux项目自动化构建工具make makefile

文章目录1. 背景2.实例3.原理4.项目清理5. 文件属性中的三个时间6. Linux下第一个小程序——进度条6.1 前置知识1&#xff1a;缓冲区6.2前置知识2&#xff1a;回车换行6.3进度条的实现7 Linux下git的”三板斧“1. 背景 一个工程中的源文件不计其数&#xff0c;其按类型、功能、…

【C++】位图+哈希切割+布隆过滤器

文章目录一、位图1.1 位图概念1.2 位图实现1.2.1 把x对应比特位0置11.2.2 把x对应比特位1置01.2.1 查看x对应比特位1.3 位图源码1.4 位图的应用二、哈希切割&#xff08;处理海量数据&#xff09;三、布隆过滤器3.1 布隆过滤器的概念3.2 布隆过滤器的应用场景3.3 布隆过滤器的实…

zookeeper安装使用

一、因使用kafka 需使用zookeeper,此处使用单节点 ZooKeeper有两种安装模式&#xff0c;最简单的方式是单机模式&#xff08;standalone mode&#xff09;&#xff0c;它只需要在一台机器上面运行&#xff0c;另一种方式是集群模式&#xff0c;集群模式需要多台服务器部署。 Z…

Java中垃圾回收(GC)基本概念

如果想真正理解GC&#xff0c;则需要循序渐进&#xff0c;由浅入深的了解GC&#xff0c;从本篇文章开始我们详细介绍Java中的GC&#xff0c;本篇文章我们通过4个主题先介绍垃圾回收的基本概念一、Java中什么是GC&#xff0c;为什么需要GC二、早期垃圾回收三、Java垃圾回收机制四…