lua 游戏架构 之 LoaderWallet 异步加载

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

类定义和初始化

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

定义 一个对象池:TablePool 类 lua 游戏架构 之 TablePool`对象池-CSDN博客https://blog.csdn.net/heyuchang666/article/details/140530648

定义了一个`cachePool`对象,用于缓存`LoaderWallet`的内部对象,减少内存分配和回收的开销。

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

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

Lua 复制代码
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已经被释放过,则输出错误日志。

Lua 复制代码
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. 返回句柄:返回加载器的句柄,用于标识这个加载操作。
Lua 复制代码
---@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`在多线程环境下使用,需要确保线程安全。

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

Lua 复制代码
--[[
   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
相关推荐
小蜗牛慢慢爬行10 分钟前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
小扳2 小时前
微服务篇-深入了解 MinIO 文件服务器(你还在使用阿里云 0SS 对象存储图片服务?教你使用 MinIO 文件服务器:实现从部署到具体使用)
java·服务器·分布式·微服务·云原生·架构
盛派网络小助手10 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
快乐非自愿15 小时前
分布式系统架构2:服务发现
架构·服务发现
2401_8543910815 小时前
SSM 架构中 JAVA 网络直播带货查询系统设计与 JSP 有效实现方法
java·开发语言·架构
264玫瑰资源库15 小时前
从零开始C++棋牌游戏开发之第二篇:初识 C++ 游戏开发的基本架构
开发语言·c++·架构
神一样的老师15 小时前
面向高精度网络的时间同步安全管理架构
网络·安全·架构
2401_8570262315 小时前
基于 SSM 架构的 JAVA 网络直播带货查询系统设计与 JSP 实践成果
java·开发语言·架构
9527华安15 小时前
FPGA实现MIPI转FPD-Link车载同轴视频传输方案,基于IMX327+FPD953架构,提供工程源码和技术支持
fpga开发·架构·mipi·imx327·fpd-link·fpd953
DT辰白15 小时前
如何解决基于 Redis 的网关鉴权导致的 RESTful API 拦截问题?
后端·微服务·架构