【GameFramework框架内置模块】8、文件系统(File System)

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

【GameFramework框架】系列教程目录:
https://blog.csdn.net/q764424567/article/details/135831551

最近好忙,鸽了好久。不能颓废了,继续发力。

今天分享的是GF框架的File System文件系统。

二、正文

2-1、介绍

首先,引用比较官方的说法:

GF的FileSystem虚拟文件系统,使用类似磁盘存储的感念对零散的文件进行集中管理,优化资源加载时产生的内存分配,也可以对资源进行局部片段加载,极大的提升了资源加载的性能。

通俗点讲就是,我这个模块就是加载磁盘文件的,优化加载时产生的内存分配。

那么,它是怎么优化的呢?

比如说一个文件夹里面有几千个文件,传输的话会非常的慢,因为普通的文件系统是一个一个读取写入,每次读取写入都是一次磁盘IO,所以花费大量时间,而这个文件系统将会将整个文件夹当成一个压缩包,然后再进行读取写入,那么就减少了大量的IO,提高了性能。

2-2、使用说明

查看文件是否存在:

using GameFramework.FileSystem;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityGameFramework.Runtime;public class TestFileSystem : MonoBehaviour
{void Start(){FileSystemComponent fileSystemComponent = GameEntry.GetComponent<FileSystemComponent>();string fullPath = System.IO.Path.Combine(Application.persistentDataPath, "FileSystem.dat"); 检查是否存在文件系统,参数要传递的是文件系统的完整路径bool hasFileSystem = fileSystemComponent.HasFileSystem(fullPath);Debug.Log(hasFileSystem);}
}

读写文件:

using GameFramework.FileSystem;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityGameFramework.Runtime;public class TestFileSystem : MonoBehaviour
{void Start(){FileSystemComponent fileSystemComponent = GameEntry.GetComponent<FileSystemComponent>();// 要创建的文件系统的完整路径string fullPath = Path.Combine(Application.persistentDataPath, "FileSystem.dat");// 要创建的文件系统最大能容纳文件数量int maxFileCount = 16;// 要创建的文件系统最大能容纳的块数据数量int maxBlockCount = 256;// 创建文件系统(使用读写模式进行访问)IFileSystem fileSystem = fileSystemComponent.CreateFileSystem(fullPath, FileSystemAccess.ReadWrite, maxFileCount, maxBlockCount);// 将字节数组写入指定文件byte[] buffer = new byte[1024]; // 读取文件片段使用的 buffer,用此方式能够复用 buffer 来消除 GCAllocbool result = fileSystem.WriteFile("FileName.dat", buffer);// 将流写入指定文件FileStream fs = new FileStream("FileName.dat", FileMode.Create, FileAccess.Write);bool result2 = fileSystem.WriteFile("FileName.dat", fs);// 将物理文件写入指定文件bool result3 = fileSystem.WriteFile("FileName.dat", @"E:\PhysicalFileName.dat");}
}

2-3、实现及代码分析

File System虽说是一个独立的模块,但是一般不直接使用,通常要配合其他模块,比较典型的例子就是资源打包和读取额时候。

因为在做资源更新的时候,会将资源进行整理分包加载,资源管理器ResourceComponent继承了File System文件系统,只需要在构建ResoucrceCollection.xml时,在对应的资源Resources标签下指定FileSystem属性即可:在这里插入图片描述
Build资源的时候,会自动将此Resource放入指定的文件系统,运行加载资源时,也会自动去对应的FileSystem文件中进行加载。

下面就以打包和加载来分析FileSystem文件系统的代码实现。

2-3-1、打包代码分析

1、点击Start Build Resource按钮后,会调用BuildResource函数:
在这里插入图片描述
在这里插入图片描述

/// 资源生成器。
internal sealed class ResourceBuilder : EditorWindowprivate void BuildResources(){if (m_Controller.BuildResources()){Debug.Log("Build resources success.");SaveConfiguration();}else{Debug.LogWarning("Build resources failure.");}}
}

2、创建文件系统,存储在文件系统中:

public sealed partial class ResourceBuilderController
{public bool BuildResources(){......AssetBundleManifest assetBundleManifest = BuildPipeline.BuildAssetBundles(workingPath, assetBundleBuildDatas, buildAssetBundleOptions, GetBuildTarget(platform));......if (OutputPackageSelected){CreateFileSystems(m_ResourceDatas.Values, outputPackagePath, m_OutputPackageFileSystems);}......
}

3、创建文件系统后,遍历所有的打包资源,获取标记了FileSystem标签的项,加入文件系统:

private void CreateFileSystems(IEnumerable<ResourceData> resourceDatas, string outputPath, Dictionary<string, IFileSystem> outputFileSystem)
{outputFileSystem.Clear();string[] fileSystemNames = GetFileSystemNames(resourceDatas);if (fileSystemNames.Length > 0 && m_FileSystemManager == null){m_FileSystemManager = GameFrameworkEntry.GetModule<IFileSystemManager>();m_FileSystemManager.SetFileSystemHelper(new FileSystemHelper());}foreach (string fileSystemName in fileSystemNames){int fileCount = GetResourceIndexesFromFileSystem(resourceDatas, fileSystemName).Length;string fullPath = Utility.Path.GetRegularPath(Path.Combine(outputPath, Utility.Text.Format("{0}.{1}", fileSystemName, DefaultExtension)));IFileSystem fileSystem = m_FileSystemManager.CreateFileSystem(fullPath, FileSystemAccess.Write, fileCount, fileCount);outputFileSystem.Add(fileSystemName, fileSystem);}
}

4、写入文件系统,把每个经过加密处理的资源写入到指定的文件系统中:

public sealed partial class ResourceBuilderController
{private bool ProcessOutput(Platform platform, string outputPackagePath, string outputFullPath, string outputPackedPath, bool additionalCompressionSelected, string name, string variant, string fileSystem, ResourceData resourceData, byte[] bytes, int length, int hashCode, int compressedLength, int compressedHashCode){string fullNameWithExtension = Utility.Text.Format("{0}.{1}", GetResourceFullName(name, variant), GetExtension(resourceData));if (OutputPackageSelected){if (!string.IsNullOrEmpty(fileSystem)){if (!m_OutputPackageFileSystems[fileSystem].WriteFile(fullNameWithExtension, bytes)){return false;}}}}
}
2-3-2、加载代码分析

1、使用ResourceManager加载资源:

internal class ResourceManager : GameFrameworkModule, IResourceManager
{/// 异步加载资源。public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData){m_ResourceLoader.LoadAsset(assetName, assetType, priority, loadAssetCallbacks, userData);}
}

2、使用Resource任务池加载,使用多个LoadResourceAgent代理,异步加载资源,每个资源加载都是一个LoadAssetTask,每个任务开始时都会分配一个LoadResourceAgent代理:

internal sealed class TaskPool<T> where T : TaskBase
{public void Update(float elapseSeconds, float realElapseSeconds){ProcessRunningTasks(elapseSeconds, realElapseSeconds);ProcessWaitingTasks(elapseSeconds, realElapseSeconds);}//处理任务池等待列表private void ProcessWaitingTasks(float elapseSeconds, float realElapseSeconds){LinkedListNode<T> current = m_WaitingTasks.First;while (current != null && FreeAgentCount > 0){ITaskAgent<T> agent = m_FreeAgents.Pop();LinkedListNode<ITaskAgent<T>> agentNode = m_WorkingAgents.AddLast(agent);T task = current.Value;LinkedListNode<T> next = current.Next;//LoadResourceAgent代理开始读取资源StartTaskStatus status = agent.Start(task);current = next;...}}
}

3、资源文件的读取,使用了资源加载代理辅助器,分别为LoadFromFile、LoadFromMemory两种不同的加载方式:

/// 默认加载资源代理辅助器。
public class DefaultLoadResourceAgentHelper : LoadResourceAgentHelperBase, IDisposable
{/// 通过加载资源代理辅助器开始异步读取资源文件。public override void ReadFile(string fullPath){m_FileAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fullPath);}/// 通过加载资源代理辅助器开始异步读取资源文件。public override void ReadFile(IFileSystem fileSystem, string name){FileInfo fileInfo = fileSystem.GetFileInfo(name);m_FileAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fileSystem.FullPath, 0u, (ulong)fileInfo.Offset);}/// 通过加载资源代理辅助器开始异步读取资源二进制流。public override void ReadBytes(string fullPath){m_UnityWebRequest = UnityWebRequest.Get(Utility.Path.GetRemotePath(fullPath));m_UnityWebRequest.SendWebRequest();}/// 通过加载资源代理辅助器开始异步读取资源二进制流。public override void ReadBytes(IFileSystem fileSystem, string name){byte[] bytes = fileSystem.ReadFile(name);m_LoadResourceAgentHelperReadBytesCompleteEventHandler(this, LoadResourceAgentHelperReadBytesCompleteEventArgs.Create(bytes));}
}

4、最后,通过LoadMain,从Bundle中读取资源,最后运行监听事件LoadComplete,加载全部完成:

/// 默认加载资源代理辅助器。
public class DefaultLoadResourceAgentHelper : LoadResourceAgentHelperBase, IDisposable
{/// 通过加载资源代理辅助器开始异步读取资源文件。public override void ReadFile(string fullPath){m_FileAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fullPath);}/// 通过加载资源代理辅助器开始异步读取资源文件。public override void ReadFile(IFileSystem fileSystem, string name){FileInfo fileInfo = fileSystem.GetFileInfo(name);m_FileAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fileSystem.FullPath, 0u, (ulong)fileInfo.Offset);}/// 通过加载资源代理辅助器开始异步读取资源二进制流。public override void ReadBytes(string fullPath){m_UnityWebRequest = UnityWebRequest.Get(Utility.Path.GetRemotePath(fullPath));m_UnityWebRequest.SendWebRequest();}/// 通过加载资源代理辅助器开始异步读取资源二进制流。public override void ReadBytes(IFileSystem fileSystem, string name){byte[] bytes = fileSystem.ReadFile(name);m_LoadResourceAgentHelperReadBytesCompleteEventHandler(this, LoadResourceAgentHelperReadBytesCompleteEventArgs.Create(bytes));}
}

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

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

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

相关文章

登录-前端部分

登录表单和注册表单在同一个页面中&#xff0c;通过注册按钮以及返回按钮来控制要显示哪个表单 一、数据绑定和校验 &#xff08;1&#xff09;绑定数据&#xff0c;复用注册表单的数据模型&#xff1a; //控制注册与登录表单的显示&#xff0c; 默认false显示登录 true时显…

【MySQL】4. 表的操作

表的操作 1. 创建表 语法&#xff1a; CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;说明&#xff1a; field 表示列名 datatype 表示列的类型 character set 字符集&#xff0c…

java方法的引用传递和值传递

1、方法的值参数传递 下面代码&#xff0c;它会在控制台输出什么&#xff1f; public class ArrayTest {public static void main(String[] args) {int number 100;System.out.println(number);change(number);System.out.println(number);}public static void change(int n…

vue3使用qrcodejs2-fix生成背景透明的二维码

qrcodejs官方仓库&#xff1a;GitHub - davidshimjs/qrcodejs: Cross-browser QRCode generator for javascript qrcodejs2-fix 是一个用于生成QR码的JavaScript库&#xff0c;使用的时候先安装&#xff0c;然后通过设置前景色和背景色可以控制显示的二维码效果。想生成透明背…

手撕算法-二叉树的镜像

题目描述 操作给定的二叉树&#xff0c;将其变换为源二叉树的镜像。数据范围&#xff1a;二叉树的节点数 0≤_n_≤1000 &#xff0c; 二叉树每个节点的值 0≤_val_≤1000要求&#xff1a; 空间复杂度 O(n) 。本题也有原地操作&#xff0c;即空间复杂度 O(1) 的解法&#xff0c…

士兵排列问题

解法一&#xff1a; deque实现队头入队和队尾入队即可得到编号排列&#xff0c;每个士兵有二个属性&#xff1a;编号、能力值。 #include<iostream> #include<algorithm> #include<deque> #include<vector> using namespace std; #define endl \n st…

汇率与政治的关系?Anzo Capital实例举证

投资者在使用特定货币对交易时&#xff0c;交易者应关注交易所用货币国家的主要政治新闻。众所周知&#xff0c;政治和金融密切相关&#xff0c;因此重要政治消息的发布会对汇率产生强烈影响。 Anzo Capital实例举证&#xff1a;汇率与政治的关系。 其中一个例子&#xff0c…

限流的常见算法

计数器法 计数器算法&#xff0c;也成固定窗口法。可以控制在固定的时间窗口内&#xff0c;允许通过的最大的请求数。 例如&#xff0c;我们设定时间间隔窗口为1分钟&#xff0c;该窗口内的最大请求数max为100。当第1个请求到来时&#xff0c;我们记录下当前窗口内的第一个请…

文件系统 与 软硬链接

目录 一、文件系统 认识磁盘 磁盘存储的逻辑抽象结构 块组的内容 inode Table Data blocks inode Bitmap Block Bitmap Group Descriptor Table Super Block 理解目录 二、软硬链接 软链接​ 硬链接 硬链接数 一、文件系统 之前的博客主题叫做"进程打开文…

Winform编程详解十五:ProgressBar 进度条控件

一、属性介绍 1. (Name) 控件的对象标识符ID 2. BackColor 控件的背景颜色 3. Cursor 鼠标移过该控件显示的光标样式 4. ForeColor 控件的文本颜色 5. UseWaitCursor 使用鼠标的等待光标 6. Enabled 控件激活状态 7. Maximum 进度条的最大值 8. Minimum 进度条的最小…

【物联网应用】基于云计算的智能化温室种植一体化平台

目录 第一章 作品概述 1.1. 作品名称 1.2. 应用领域 1.3.主要功能 1.4.创新性说明 第二章 需求分析 2.1 现实背景 2.2 用户群体及系统功能 2.3 竞品分析 第三章 技术方案 3.1. 硬件组成与来源 3.2. 硬件设计合理性 3.3. 硬件系统设计图 3.4. 接口的通用性与可扩展性 3.5. 代码规…

vue中判断是否使用自定义插槽

在封装自定义组件时&#xff0c;需要判断使用者是否使用了插槽<slot"aaa">&#xff0c;如果没有则使用一个组件中默认的值&#xff0c;反之就用传入的内容<template name"aaa"></template>,实现如下&#xff1a; <div class"lin…

苍穹外卖-day06:HttpClient、微信小程序开发、微信登录(业务流程)、导入商品浏览功能代码(业务逻辑)

苍穹外卖-day06 课程内容 HttpClient微信小程序开发微信登录导入商品浏览功能代码 功能实现&#xff1a;微信登录、商品浏览 微信登录效果图&#xff1a; 商品浏览效果图&#xff1a; 1. HttpClient 1.1 介绍 HttpClient 是Apache Jakarta Common 下的子项目&#xff0c;…

深度解析大模型:概念、架构与应用价值

大模型&#xff0c;作为一种前沿的人工智能技术&#xff0c;已经成为深度学习领域的研究热点和发展趋势。这一概念主要指代那些规模庞大、参数数量众多、结构复杂的机器学习模型&#xff0c;尤其是深度神经网络模型。以下是对大模型的详细介绍&#xff1a; 基本概念 规模参数量…

文件系统I/O FATFS RW 源码分析

文件系统I/O FATFS RW 源码分析 0 参考 FatFs 是用于小型嵌入式系统的通用 FAT/exFAT 文件系统模块。FatFs 整个项目都按照 ANSI C (C89) 编写。与存储器 I/O 解耦良好&#xff0c;便于移植到 8051、PIC、AVR、ARM、Z80、RX 等小型微控制器中。 下面是关于 FAT 文件系统格式…

20.回文链表

给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;head …

linux 安装常用软件

文件传输工具 sudo yum install –y lrzsz vim编辑器 sudo yum install -y vimDNS 查询 sudo yum install bind-utils用法可以参考文章 《掌握 DNS 查询技巧&#xff0c;dig 命令基本用法》 net-tools包 yum install net-tools -y简单用法&#xff1a; # 查看端口占用情况…

浮点数加法

浮点数有时候计算结果会出现长尾小数&#xff0c;例如0.10.110.21000000000002&#xff0c;这种结果很麻烦。用包装类就可以轻松的解决这个问题&#xff0c;不过想着很久没写加法了&#xff0c;高精度加法也不咋写了&#xff0c;自己造下轮子熟悉一下算法&#xff0c;于是就写了…

【学习学习】学习金字塔

学习金字塔&#xff08;Cone of Learning&#xff09;&#xff0c;全称学习吸收率金字塔&#xff0c;是一种现代学习方式的理论。网上流传它是美国缅因州的国家训练实验室&#xff08;National Training Laboratories&#xff09;研究成果&#xff0c;用数字形式形象显示了采用…

音视频实战---音频重采样

1、使用swr_alloc()创建重采样实例 2、使用av_opt_set_int函数设置重采样输入输出参数 3、使用swr_init函数初始化重采样器 4、使用av_get_channel_layout_nb_channels函数计算输入源的通道数 5、给输入源分配内存空间–av_samples_alloc_array_and_samples 6、计算输出采…