lua 游戏架构 之 LoaderWallet 异步加载

news2024/11/12 5:21:05

定义了一个名为`LoaderWallet` class,用于管理资源加载器(Loader)。这个类封装了资源加载的功能,包括异步加载,以及资源的释放和状态查询。下面是对代码的详细解释:

### 类定义和初始化

这里定义了一个名为`LoaderWallet`的类,并使用`SimpleClassUtil:class()`方法进行初始化。

定义 一个对象池:TablePool 类 lua 游戏架构 之 TablePool`对象池-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/heyuchang666/article/details/140530648
定义了一个`cachePool`对象,用于缓存`LoaderWallet`的内部对象,减少内存分配和回收的开销。

local cachePool =
    TablePool:new(
        16,
        nil,
        function(t)
            for i, _ in pairs(t) do
                t[i] = nil
            end
        end
)

owner是一个成员变量,用于存储LoaderWallet的拥有者。这个拥有者可以是任何对象,通常是一个游戏对象或场景对象,用于管理资源加载。

function LoaderWallet:initialize(owner)
    self.owner = owner
end

function LoaderWallet:setOwner(owner)
    self.owner = owner
    self.loaders = cachePool:getObj()
    self.callbacks = cachePool:getObj()
end

释放所有内部加载器,并释放loaderscallbacks对象。如果LoaderWallet已经被释放过,则输出错误日志。

function LoaderWallet:release()
    if not self.owner then
        Logger.error("Try to Release LoaderWallet Twice. You should check if nil firstly.")
        return
    end
    for _, loader in pairs(self.loaders) do
        loader:release()
    end
    cachePool:releaseObj(self.loaders)
    cachePool:releaseObj(self.callbacks)
    self.owner = nil
    self.loaders = nil
    self.callbacks = nil
    if self.rlsFunc then
        self.rlsFunc(self)
    end
end
设计方法 于查询加载器的状态,包括是否完成、加载进度、是否正在加载以及句柄是否有效。
  • isComplete
  • getProgress
  • isLoading
  • isValidHandle
设计方法用于标记资源是否需要卸载、释放加载器、获取加载完成的资源以及获取子资源
  • markUnloadParam
  • releaseHandle
  • getAsset
  • getSubAsset
设计 异步加载不同类型的资源 方法 loadAssetAsync
  1. 创建资源加载器:使用g.loaderManager:newAssetLoader(path)创建一个新的资源加载器实例,path是资源的路径。
  2. 判断是否使用队列:如果提供了queue参数,则调用loader:loadQueued(queue, self.onLoaderDone, self)将资源加载操作加入队列中,并指定加载完成后的回调函数self.onLoaderDone。否则,调用loader:loadAsync(self.onLoaderDone, self)直接异步加载资源。
  3. 保存加载器实例和回调函数:将加载器实例和对应的回调函数保存到self.loadersself.callbacks表中,使用加载器的句柄(handleID)作为键。
  4. 返回句柄:返回加载器的句柄,用于标识这个加载操作。
---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@param queue CS.Topjoy.Base.ResourceManagement.OperationHandles.OperationQueue
---@return number @handle
function LoaderWallet:loadAssetAsync(path, callback, queue)
    ---@type AssetLoader
    local loader = g.loaderManager:newAssetLoader(path)
    if queue then
        loader:loadQueued(queue, self.onLoaderDone, self)
    else
        loader:loadAsync(self.onLoaderDone, self)
    end
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

异步加载资源,并允许用户指定加载完成后的回调函数。这对于需要异步加载资源并处理加载结果的应用场景非常有用,比如游戏中的资源预加载、UI资源的动态加载等。

### 注意事项

1. **资源管理**:确保在不再需要资源时及时释放,避免内存泄漏。
2. **错误处理**:在资源加载失败时,应记录错误信息,便于调试。
3. **线程安全**:如果`LoaderWallet`在多线程环境下使用,需要确保线程安全。

这段代码主要用于游戏开发中的资源管理,通过封装资源加载器,简化了资源加载和管理的流程。

--[[
   Desc: Loader持有者,封装Release
--]]

---@class LoaderWallet
local LoaderWallet = SimpleClassUtil:class()
local cachePool =
    TablePool:new(
        16,
        nil,
        function(t)
            for i, _ in pairs(t) do
                t[i] = nil
            end
        end
)
function LoaderWallet:initialize(owner)
    self.owner = owner
end

function LoaderWallet:setOwner(owner)
    self.owner = owner
    self.loaders = cachePool:getObj()
    self.callbacks = cachePool:getObj()
end

--- 释放所有的内部loader
function LoaderWallet:release()
    if not self.owner then
        Logger.error("Try to Release LoaderWallet Twice. You should check if nil firstly.")
        return
    end
    for _, loader in pairs(self.loaders) do
        loader:release()
    end
    cachePool:releaseObj(self.loaders)
    cachePool:releaseObj(self.callbacks)
    self.owner = nil
    self.loaders = nil
    self.callbacks = nil
    if self.rlsFunc then
        self.rlsFunc(self)
    end
end

---@private
---@param loader BaseLoader
function LoaderWallet:onLoaderDone(loader)
    if self.owner==nil then
        loader:release()
        return
    end
    local handle = loader.handleID
    local cb = self.callbacks[handle]
    if cb then
        cb(self.owner, handle)
    end
end

---@param handle number
---@return boolean
function LoaderWallet:isComplete(handle)
    local loader = self.loaders[handle]
    if loader then
        return loader.isComplete
    end
    return false
end

---@param handle number
---@return number @[0, 1]
function LoaderWallet:getProgress(handle)
    local loader = self.loaders[handle]
    if loader then
        return loader:getProgress()
    end
    return 0
end

---@param handle number
---@return boolean
function LoaderWallet:isLoading(handle)
    local loader = self.loaders[handle]
    if loader then
        return loader:isLoading()
    end
    return false
end

---@param handle number
---@return boolean
function LoaderWallet:isValidHandle(handle)
    return self.loaders[handle]~=nil
end

---@param handle number
---@param unload boolean
function LoaderWallet:markUnloadParam(handle, unload)
    local loader = self.loaders[handle]
    if loader then
        loader:markUnloadParam(unload)
    else
        Logger.error("Miss Loader for handle:", handle)
    end
end

---@param handle number
function LoaderWallet:releaseHandle(handle)
    local loader = self.loaders[handle]
    if loader then
        loader:release()
        self.loaders[handle] = nil
        self.callbacks[handle] = nil
    else
        Logger.error("Miss Loader for handle:", handle)
    end
end

---@param path string
---@return boolean
function LoaderWallet:hasAnyWithPath(path)
    for _, loader in pairs(self.loaders) do
        if loader.path == path then
            return true
        end
    end
    return false
end

--- 获取加载完成后的资源。如,prefab。
---@param handle number
---@return CS.UnityEngine.Object
function LoaderWallet:getAsset(handle)
    local loader = self.loaders[handle]
    if loader then
        return loader.result
    else
        Logger.error("Miss Loader for handle:", handle)
    end
end

--- 获取子资源。如,sprite。
---@param handle number
---@param name string
---@return CS.UnityEngine.Object
function LoaderWallet:getSubAsset(handle, name)
    local loader = self.loaders[handle]
    if loader then
        return loader:getSubAsset(name)
    else
        Logger.error("Miss Loader for handle:", handle)
    end
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@param queue CS.GameYL.Base.ResourceManagement.OperationHandles.OperationQueue
---@return number @handle
function LoaderWallet:loadAssetAsync(path, callback, queue)
    ---@type AssetLoader
    local loader = g.loaderManager:newAssetLoader(path)
    if queue then
        loader:loadQueued(queue, self.onLoaderDone, self)
    else
        loader:loadAsync(self.onLoaderDone, self)
    end
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@param queue CS.GameYL.Base.ResourceManagement.OperationHandles.OperationQueue
---@return number @handle
function LoaderWallet:loadListSpriteAsync(path, callback, queue)
    ---@type ListSpriteLoader
    local loader = g.loaderManager:newListSpriteLoader(path)
    if queue then
        loader:loadQueued(queue, self.onLoaderDone, self)
    else
        loader:loadAsync(self.onLoaderDone, self)
    end
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@param queue CS.GameYL.Base.ResourceManagement.OperationHandles.OperationQueue
---@return number @handle
function LoaderWallet:loadMaterialAsync(path, callback, queue)
    ---@type MaterialLoader
    local loader = g.loaderManager:newMaterialLoader(path)
    if queue then
        loader:loadQueued(queue, self.onLoaderDone, self)
    else
        loader:loadAsync(self.onLoaderDone, self)
    end
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@param queue CS.GameYL.Base.ResourceManagement.OperationHandles.OperationQueue
---@return number @handle
function LoaderWallet:loadPrefabAsync(path, callback, queue)
    ---@type PrefabLoader
    local loader = g.loaderManager:newPrefabLoader(path)
    if queue then
        loader:loadQueued(queue, self.onLoaderDone, self)
    else
        loader:loadAsync(self.onLoaderDone, self)
    end
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@return number @handle
function LoaderWallet:loadSceneAsync(path, callback)
    ---@type SceneLoader
    local loader = Global.loaderManager:loadSceneAsync(path, self.onLoaderDone, self)
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@param queue CS.GameYL.Base.ResourceManagement.OperationHandles.OperationQueue
---@return number @handle
function LoaderWallet:loadTextAssetAsync(path, callback, queue)
    ---@type TextAssetLoader
    local loader = g.loaderManager:newTextAssetLoader(path)
    if queue then
        loader:loadQueued(queue, self.onLoaderDone, self)
    else
        loader:loadAsync(self.onLoaderDone, self)
    end
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@param queue CS.GameYL.Base.ResourceManagement.OperationHandles.OperationQueue
---@return number @handle
function LoaderWallet:loadTextureAsync(path, callback, queue)
    ---@type TextureLoader
    local loader = g.loaderManager:newTextureLoader(path)
    if queue then
        loader:loadQueued(queue, self.onLoaderDone, self)
    else
        loader:loadAsync(self.onLoaderDone, self)
    end
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@param path string
---@param callback fun(self:table, handle:number) @self是owner
---@return number @handle
function LoaderWallet:loadWwiseBankAsync(path, callback)
    ---@type WwiseBankLoader
    local loader = g.loaderManager:newWwiseBankLoader(path)
    loader:loadAsync(self.onLoaderDone, self)
    local handle = loader.handleID
    self.loaders[handle] = loader
    self.callbacks[handle] = callback
    return handle
end

---@overload fun(path:string)
---@param path string
---@param decodeBank boolean
---@param saveDecodedBank boolean
---@return number @handle
function LoaderWallet:loadWwiseBankSync(path, decodeBank, saveDecodedBank)
    ---@type WwiseBankLoader
    local loader = g.loaderManager:newWwiseBankLoader(path)
    loader.decodeBank = decodeBank
    loader.saveDecodedBank = saveDecodedBank
    loader:loadSync()
    local handle = loader.handleID
    self.loaders[handle] = loader
    return handle
end

return LoaderWallet

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

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

相关文章

初学者对 WebGL 与 WebGPU 的看法(A Beginner’s Perspective of WebGL vs WebGPU)

初学者对 WebGL 与 WebGPU 的看法(A Beginner’s Perspective of WebGL vs WebGPU) WebGL 和 WebGPU 之间的主要区别:WebGL 是什么以及它适合哪些人使用?WebGPU 是什么?它适合谁使用?WebGL 和 WebGPU 的代码…

spring事件发布器ApplicationEventPublisher的使用

1、前言 spring中有一个事件发布器,使用了观察者模式,当有事件发布的时候,事件监听者会立刻收到发布的事件。今天我们来介绍下这个事件发布器怎么使用。 2、简单使用 2.1、创建事件实体类 事件实体类需要继承ApplicationEvent。我们模拟老师发布事件的诉求。 public class T…

【51项目】基于51单片机protues交通灯的设计(完整资料源码)

基于51单片机protues交通灯的设计 一、 项目背景 1.1背景 随着科技的不断发展,LED技术在交通领域的应用越来越广泛。LED模拟交通灯作为一种新型的交通信号控制设备,以其高效、节能、环保等优点,逐渐取代了传统的交通信号灯。近年来&#xff…

【人工智能】Transformers之Pipeline(三):文本转音频(text-to-audio/text-to-speech)

​​​​​​​ 一、引言 pipeline(管道)是huggingface transformers库中一种极简方式使用大模型推理的抽象,将所有大模型分为音频(Audio)、计算机视觉(Computer vision)、自然语言处理&#x…

【深度学习入门篇 ⑨】循环神经网络实战

【🍊易编橙:一个帮助编程小伙伴少走弯路的终身成长社群🍊】 大家好,我是小森( ﹡ˆoˆ﹡ ) ! 易编橙终身成长社群创始团队嘉宾,橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官…

把当前img作为到爷爷的背景图

(忽略图大小不一致,一般UI给的图会刚好适合页面大小,我这网上找的图,难调大小,我行内的就自己随便写的宽高),另外悄悄告诉你最后有简单方法~~ 先来看看初始DOM结构代码 …

【接口自动化_12课_基于Flask搭建MockServer】

知识非核心点,面试题较少。框架搭建的过程中的细节才是面试要点 第三方接口,不方便进行测试, 自己要一个接口去进行模拟。去作为我们项目访问模拟接口。自己写一个接口,需要怎样写 一、flask:轻量级的web应用的框架 安装命令 pip install flask 1、flask-web应用 1)…

【防雷】浪涌保护器的选择与应用

浪涌保护器(SPD)是一种用于保护电气设备免受电力系统突发的电压浪涌或过电压等干扰的重要装置。供电系统由于外部受雷击、过电压影响,内部受大容量设备和变频设备的开、关、重启、短路故障等,都会产生瞬态过电压,带来日…

你下载的蓝光电影,为什么不那么清晰?

1080P 为什么糊 蓝光对应的就是 1080P分辨率为 1920 * 1080 随便抽取一帧画面,得到的就是一张有 1920 * 1080 个像素点的图片大多数电影是每秒播放 24 张图片,也就是一个 24 帧的电影 电影在电脑上的储存 压缩方案 不仅仅有如下两种,还有…

Vue3 + uni-app 微信小程序:仿知乎日报详情页设计及实现

引言 在移动互联网时代,信息的获取变得越来越便捷,而知乎日报作为一款高质量内容聚合平台,深受广大用户喜爱。本文将详细介绍如何利用Vue 3框架结合微信小程序的特性,设计并实现一个功能完备、界面美观的知乎日报详情页。我们将从…

Linux LVM扩容方法

问题描述 VMware Centos环境,根分区为LVM,大小50G,现在需要对根分区扩容。我添加了一块500G的虚拟硬盘(/dev/sdb),如何把这500G扩容到根分区? LVM扩容方法 1. 对新磁盘分区 使用fdisk /dev/sdb命令,进…

C++:类和对象1

1.类的定义 类定义在面向对象编程中是一个核心概念,它定义了对象的结构和行为。在C中,类定义包含类的名称、数据成员(也称为属性或者字段)和成员函数(也称为方法或者操作)多个部分。数据成员定义了对象的状…

2024-07-16 Unity插件 Odin Inspector5 —— Conditional Attributes

文章目录 1 说明2 条件特性2.1 DisableIf / EnableIf2.2 DisableIn / EnableIn / ShowIn / HideIn2.3 DisableInEditorMode / HideInEditorMode2.4 DisableInInlineEditors / ShowInInlineEditors / HideInInlineEditors2.5 DisableInPlayMode / HideInPlayMode2.6 ShowIf / Hi…

docker安装mysql突然无法远程连接

docker安装mysql突然莫名其妙的无法远程连接 docker安装mysql突然无法远程访问问题背景发现问题排查问题解决问题总结 docker安装mysql突然无法远程访问 问题背景 大概一年前在服务器中通过docker安装mysql5.7端口映射关系是3308->3306 前期在服务器上开方了3308端口 fir…

Python用Pyqt5制作音乐播放器

具体效果如下 需要实现的功能主要的几个有: 1、搜索结果更新至当前音乐的列表,这样播放下一首是搜素结果的下一首 2、自动播放 3、滚动音乐文本 4、音乐进度条 5、根据实际情况生成音乐列表。我这里的是下面的情况,音乐文件的格式是 歌…

图——图的遍历(DFS与BFS算法详解)

前面的文章中我们学习了图的基本概念和存储结构,大家可以通过下面的链接学习: 图的定义和基本术语 图的类型定义和存储结构 这篇文章就来学习一下图的重要章节——图的遍历。 目录 一,图的遍历定义: 二,深度优先…

【MySQL】:学习数据库必须要知道的背景知识

客户端—服务器 客户端是一个“客户端—服务器”结构的程序 C(client)—S(server) 客户端和服务器是两个独立的程序,这两个程序之间通过“网络”进行通信(相当于是两种角色) 客户端 主动发起网…

CV12_ONNX转RKNN模型(谛听盒子)

暂时简单整理一下: 1.在边缘设备上配置相关环境。 2.配置完成后,获取模型中间的输入输出结果,保存为npy格式。 3.将onnx格式的模型,以及中间输入输出文件传送到边缘设备上。 4.编写一个python文件用于转换模型格式&#xff0c…

对某根域的一次渗透测试

前言 两个月之前的一个渗透测试项目是基于某网站根域进行渗透测试,发现该项目其实挺好搞的,就纯粹的没有任何防御措施与安全意识所以该项目完成的挺快,但是并没有完成的很好,因为有好几处文件上传没有绕过(虽然从一个…

linux|多线程(一)

主要介绍了为什么要有线程 和线程的调用 和简单的对线程进行封装。 背景知识 a.重谈地址空间 我们知道物理内存的最小单元大小是4kB 物理内存是4G那么这样的单元友1M个 操作系统先描述再组织struct page[1M] 对于32位数据字长的机器,页表有2^32条也就是4G条&#…