lua 游戏架构 之 SceneLoad场景加载之 SceneBase (三)

news2024/11/27 22:25:42

谢谢大家关注一下啊我的微信 

框架上 设计一个 基类 SceneLoad:BaseSceneLoad

lua 游戏架构 之 SceneLoad场景加载(一)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/heyuchang666/article/details/140560014?spm=1001.2014.3001.5501

设计多个 场景类:NormalSceneLoad 例如:

  • BaseSceneLoad:引入基础场景加载模式。
  • NormalSceneLoad:引入普通场景加载模式。
  • PrefabSceneLoad:引入预制体场景加载模式。

lua 游戏架构 之 SceneLoad场景加载(二)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/heyuchang666/article/details/140560741?spm=1001.2014.3001.5502这次 设计一个 场景基类 SceneBase ,这个类提供了一个框架,用于处理场景的加载、初始化、激活、释放等生命周期管理,以及进度更新和用户界面显示。开发者需要根据具体的场景需求,重写一些虚函数以实现特定的功能。

定义 这个类的构造函数或初始化函数:

1. `self._name = params.name` 场景名字

2. `self._dataProgress = 0` 和 `self._totalProgress = 0`:
   - 这两行代码初始化了两个私有变量`_dataProgress`和`_totalProgress`,分别表示数据加载的进度和总进度,初始值都为0。

3. `self._loadingView = nil`:
   - 这行代码初始化了一个私有变量`_loadingView`,并将其设置为`nil`。用于存储加载界面 进度条。

4. `self._data = params.data`:存储需要加载的数据。

5. `self._active = false`:当前模块或场景是否处于活动状态。

6. `self._extra_res_loader = {}`:用于存储额外的资源加载器。

7. `self._autoClosePanles = {}`:用于存储需要自动关闭的面板。

8. `self._sceneLoad = nil`:用于存储场景加载的相关信息。

9. `self._isDispose = false`:用于表示当前对象是否已经被释放。

10. `self._progressConfig = {}`:存储进度配置信息。

11. `self._progressValue = {}`:存储进度值。

12. `self._isResumeing = false`:是否正在恢复。

然后 设计函数思路:

  • `SceneBase` 类包含初始化函数 `initialize`,它接收参数 `params` 并根据这些参数设置场景的基础属性。
  •  `getName`、`isActive`、`setActive` 等函数用于获取和设置场景的状态。
  • `isInitScene` 函数用于判断当前场景是否是初始场景,这里默认返回 `false`。
  •  `getSceneLoad` 函数返回与场景相关的加载对象。
  • `onDestroyScene` 函数用于在场景销毁时进行清理工作,需要重写。
  • `getLoadingLuaPath`、`getScenePrefabResPath` 等函数用于获取加载资源的路径,需要重写以适应具体场景。
  • `loadUnitySceneAsync` 函数用于异步加载Unity场景。
  • `onSceneResStartLoad`、`onSceneResLoaded` 函数分别在场景资源开始加载和加载完成后调用。
  •  `loadScenePrefab` 函数用于加载场景Prefab。
  • `onProgress` 函数用于更新加载进度,可能会显示或更新加载界面。
  •  `setProgressConfig` 和 `setProgressValue` 函数用于设置进度配置和进度值。
  • `initData`、`isInitDataComplete`、`getInitDataProgress` 等函数用于初始化场景数据。
  • `getInterimLoadPercent`、`getScenePercent`、`getExtraDataTotalPercent` 函数用于获取不同阶段的加载百分比。
  • `onExtraDataProgress`、`onExtraDataCompleted` 函数用于处理额外数据的加载进度。
  • - `closeLoadingPanel` 函数用于关闭加载面板。
  • - `onLoadingCompleted` 函数在加载完全完成后调用。
  • - `onFinish` 函数用于处理场景加载完成的后续工作。
  • - `enterWithData` 函数用于进入场景并传递数据。
  • - `resumeScene` 函数用于恢复场景状态。
  • - `onSceneExit` 函数在场景退出时调用。
  • - `addAutoClosePanle`、`getAutoClosePanleList`、`clearAutoClosePanle` 函数用于管理自动关闭的面板列表。
  • - `getExtraLoaderByPath` 函数根据路径获取额外的加载器。
  • - `createSceneLoad` 函数用于创建场景加载对象,根据不同的场景类型实例化不同的加载类。
  • - `addCmd`、`executeCmd`、`executeQueue` 函数用于管理和执行命令队列,这可能是用于按顺序执行特定的加载或初始化任务。

代码:

--[[
    Description: 场景基类
--]]
---
local SceneBase = class("SceneBase")

function SceneBase:initialize(params)
    self._name = params.name
    self._dataProgress = 0
    self._totalProgress = 0
    self._loadingView = nil

    self._data = params.data
    self._active = false
    self._extra_res_loader = {}

    self._autoClosePanles = {}

    self._sceneLoad = nil

    self._isDispose = false

    self._progressConfig = {}

    self._progressValue = {}
    self._isResumeing = false

    self:setProgressConfig(SceneManager.stateEnum.loadLoadingScene, self:getInterimLoadPercent())
    self:setProgressConfig(SceneManager.stateEnum.loadNewScene, self:getScenePercent())
    self:setProgressConfig(SceneManager.stateEnum.loadingNewData, self:getExtraDataTotalPercent())
end

function SceneBase:dispose()
    if self._isDispose then
        -- 解决onNewSceneLoaded,onNewSceneFinish 问题
        return
    end
    self._isDispose = true
    self._name = nil

    self._dataProgress = nil
    self._totalProgress = nil
    self._loadingView = nil

    self._data = nil

    if self._sceneRoot then
        print("release scene self._sceneRoot")
        CSharpImport.GameObject.Destroy(self._sceneRoot)
        self._sceneRoot = nil
    end

    for i, v in pairs(self._extra_res_loader) do
        v:release()
    end

    self._extra_res_loader = nil

    self:releaseSceneLoad()
end

function SceneBase:releaseSceneLoad()
    if self._sceneLoad then
        self._sceneLoad:dispose()
        self._sceneLoad = nil
    end
end

function SceneBase:getName()
    return self._name
end

---@return boolean
function SceneBase:isActive()
    return self._active
end

---@param isActive boolean
function SceneBase:setActive(isActive)
    self._active = isActive
end

---@return boolean 是否是起始场景
function SceneBase:isInitScene()
    return false
end

function SceneBase:getSceneLoad()
    return self._sceneLoad
end

-- 此处为切换场景时,由场景管理器通知释放场景lua表,根据各自场景自身需求做处理
function SceneBase:onDestroyScene()
    assert(false, "override")
end

function SceneBase:getLoadingLuaPath()
end

function SceneBase:getScenePrefabResPath()
    assert(false, "override")
end

function SceneBase:getScenePrefab()
    return self._sceneRoot
end

function SceneBase:getSceneResPath()
    assert(false, "override")
end

function SceneBase:loadUnitySceneAsync()
    local path = self:getSceneResPath()
    return g.loaderManager:loadSceneAsync(path)
end

function SceneBase:onSceneResStartLoad()
end
function SceneBase:onSceneResLoaded()
end

function SceneBase:loadScenePrefab(prefabPath)
    return Global.loaderManager:loadPrefabAsync(prefabPath)
end

function SceneBase:getSceneObj()
    return self._sceneObj
end

function SceneBase:onSceneSwitchStart()
end

function SceneBase:onPreSceneExit(finishCallback)
    assert(false, "override")
end
--- 在newScene 的onSceneResLoaded之后调用
--- 注意,此时Scene对象已经调用过dispose
function SceneBase:onNewSceneLoaded()
    assert(false, "override")
end

function SceneBase:onNewSceneStartLoaded()
    -- assert(false, "override")
end

--- 在newScene 的 onExtraDataCompleted 之前调用
--- 注意,此时Scene对象已经调用过dispose
function SceneBase:onNewSceneFinish(finishCallback)
    assert(false, "override")
end

---@param progress number
function SceneBase:onProgress(progress)
    if progress == 0 then
        if not self._loadingView then
            local panelPath = self:getLoadingLuaPath()
            if panelPath then
                print("show scene loading")
                self._loadingView =
                    g.uiManager:showPanel(
                    panelPath,
                    self:createLoadingPanelParam(),
                    function()
                        self:onLoadingPanelOpen()
                    end
                )
            end
        end
    end
    if self._loadingView and self._loadingView:getState() == UIManager.State.Normal then
        self._loadingView:setProgress(progress)
    end
end

function SceneBase:setProgressConfig(key, percent)
    self._progressConfig[key] = percent
end

function SceneBase:setProgressValue(key, value)
    self._progressValue[key] = value
    local totalProgress = 0
    for cKey, cValue in pairs(self._progressConfig) do
        local pWeight = self._progressConfig[cKey] or 0
        local pValue = self._progressValue[cKey] or 0
        totalProgress = totalProgress + pWeight * pValue
        print("setProgressValue", cKey, pValue, pWeight)
    end

    self:onProgress(totalProgress)
    print("setProgressValue totalProgress", key, totalProgress)
end
function SceneBase:createLoadingPanelParam()
end
function SceneBase:onLoadingPanelOpen()
end

function SceneBase:initData()
end
---@return boolean @初始化完成返回true
function SceneBase:isInitDataComplete()
    return true
end
function SceneBase:getInitDataProgress()
    return 1
end
function SceneBase:getInterimLoadPercent()
    return 0.02
end

function SceneBase:getScenePercent()
    return 0.4
end

function SceneBase:getSceneType()
    return SceneEnum.sceneType.unity
end

function SceneBase:getExtraDataTotalPercent()
    return 1 - self:getInterimLoadPercent() - self:getScenePercent()
end

--@desc 进行扩展数据加载
---@return number  @ 返回加载进度百分比
function SceneBase:onExtraDataProgress()
    return self._dataProgress
end

---@param call function
function SceneBase:onExtraDataCompleted(call)
    self._dataProgress = 1
    self._totalProgress = 1
    call()
end

---@param call function
function SceneBase:closeLoadingPanel(call)
    if self._loadingView then
        -- 并不需要等待loading完全结束
        g.uiManager:hidePanel(self:getLoadingLuaPath())
        self._loadingView = nil
        if call then
            call()
        end
    else
        if call then
            call()
        end
    end
end

--@desc 完全结束
function SceneBase:onLoadingCompleted()
end

function SceneBase:onFinish(call)
    self:enterWithData(self._data, 
        function()
            self:closeLoadingPanel(call)
        end
    )
end

function SceneBase:enterWithData(data, call)
    call()
end

function SceneBase:resumeScene(data)
    self._isResumeing = true
    self:onPreResumeSceneExit(data, function()
        self:onSceneExit()
        self:onResumeSceneExit(data)
        self:setActive(true)
        self:enterWithData(self._data, 
            function()
                self:onPostResumeScene(data)
            end
        )
    end)
end

function SceneBase:onPreResumeSceneExit(data, callBack)
    if callBack then
        callBack()
    end
end

function SceneBase:onPostResumeScene(data)
    self._isResumeing = false
end

--@desc 当场景退出
function SceneBase:onSceneExit()
    self:setActive(false)
end

function SceneBase:onResumeSceneExit(data)
end

function SceneBase:addAutoClosePanle(panelUiName)
    self._autoClosePanles[#self._autoClosePanles + 1] = panelUiName
end

function SceneBase:getAutoClosePanleList()
    return self._autoClosePanles
end

function SceneBase:clearAutoClosePanle()
    self._autoClosePanles = {}
end

function SceneBase:getExtraLoaderByPath(path)
    return self._extra_res_loader[path]
end

---@param curScene SceneBase
---@return BaseSceneLoad
function SceneBase:createSceneLoad(hasStacked)
    local sceneType = self:getSceneType()
    if sceneType == SceneEnum.sceneType.AdditivePrefab then
        self._sceneLoad = AdditiveSceneLoad:new()
        Logger.filter("Scene step", "AdditiveSceneLoad:initialize", self:getName(), debug.traceback())

    elseif sceneType == SceneEnum.sceneType.prefab then
        self._sceneLoad = PrefabSceneLoad:new()
        Logger.filter("Scene step", "PrefabSceneLoad:initialize", self:getName(), debug.traceback())

    elseif sceneType == SceneEnum.sceneType.dontDestoryUnit then
        if hasStacked then
            Logger.filter("Scene step", "UnloadAdditiveSceneLoad:initialize", self:getName(), debug.traceback())
            self._sceneLoad = UnloadAdditiveSceneLoad:new()
        else
            self._sceneLoad = DontDestorySceneLoad:new()        
            Logger.filter("Scene step", "DontDestorySceneLoad:initialize", self:getName(), debug.traceback())
        end
    elseif sceneType == SceneEnum.sceneType.unloadAdditivePrefab then
        self._sceneLoad = UnloadAdditiveSceneLoad:new()
        Logger.filter("Scene step", "UnloadAdditiveSceneLoad:initialize", self:getName(), debug.traceback())
    else
        self._sceneLoad = NormalSceneLoad:new()
        Logger.filter("Scene step", "NormalSceneLoad:initialize", self:getName(), debug.traceback())
    end


    return self._sceneLoad
end
function SceneBase.addCmd(queue, func, object, p1, p2, p3)
    queue[#queue + 1] = {func = func, obj = object, param1 = p1, param2 = p2, param3 = p3}
end

function SceneBase:executeCmd(queue, cmdIndex)
    local info = queue[cmdIndex]

    if info.obj then
        info.func(info.obj, info.param1, info.param2, info.param3)
    else
        info.func(info.param1, info.param2, info.param3)
    end
end

function SceneBase:executeQueue(q, cmdIndex, breakExecuteCallback)
    assert(q, "执行命令队列不能为空")
    local total = #q
    local tmpCmdIndex = cmdIndex
    if tmpCmdIndex < total then
        local cmdExeStart = os.clock()

        while (os.clock() - cmdExeStart) < 0.015 and tmpCmdIndex < total do
            tmpCmdIndex = tmpCmdIndex + 1
            self:executeCmd(q, tmpCmdIndex)
            if breakExecuteCallback and breakExecuteCallback() then
                break
            end
        end
        -- print("executeQueue", cmdIndex, tmpCmdIndex, tmpCmdIndex - cmdIndex, os.clock() - cmdExeStart)
        return false, tmpCmdIndex
    else
        return true, tmpCmdIndex
    end
end

return SceneBase

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

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

相关文章

无需业务改造,一套数据库满足 OLTP 和 OLAP,GaiaDB 发布并行查询能力

在企业中通常存在两类数据处理场景&#xff0c;一类是在线事务处理场景&#xff08;OLTP&#xff09;&#xff0c;例如交易系统&#xff0c;另一类是在线分析处理场景&#xff08;OLAP&#xff09;&#xff0c;例如业务报表。 OLTP 数据库擅长处理数据的增、删、改&#xff0c…

STM32测测速---编码电机读取速度的计算

1、首先先了解一下计算的公式 速度计算&#xff1a; 轮胎每转一圈的脉冲数取决于编码器的分辨率&#xff0c;可由下面公式进行计算&#xff1a; PPR是电机的线数 以GA25-370电机为例。 图片来源&#xff1a;第四节&#xff1a;STM32定时器&#xff08;4.JGA25-370霍尔编码器…

规范:前端工程代码规范

准备工作 前端工程化介绍 前端工程化是指将前端开发流程标准化、自动化和模块化的过程。以下是一些常见的步骤或配置&#xff1a; 代码版本控制&#xff1a;使用 Git 等版本控制系统来管理代码的变更和协作。 依赖管理&#xff1a;使用 npm 或 yarn 等包管理工具来管理项目依…

园区道路车辆智能管控视频解决方案,打造安全畅通的园区交通环境

一、背景需求分析 随着企业园区的快速发展和扩张&#xff0c;道路车辆管理成为了保障园区秩序、提升运营效率及确保员工安全的重要任务。针对这一需求&#xff0c;旭帆科技TSINGSEE青犀提出了一种企业园区道路车辆管控的解决方案&#xff0c;通过整合视频监控、智能识别等技术…

6.2 基础功能介绍

本节重点介绍 : 数据源操作新增一个数据源dashboard操作folder操作alerting操作用户和组操作 本节重点总结 : 数据源操作dashboard操作folder操作alerting操作用户和组操作

linux时间服务器——软件安装,配置时间服务器客户端 ,配置时间服务器服务端

1 、软件安装 # 设置当前时区 [rootlocalhost ~] # timedatectl set-timezone Asia/Shanghai [rootlocalhost ~] # yum install -y chrony [rootlocalhost ~] # systemctl enable --now chronyd [rootserver1 ~] # cat /etc/chrony.conf # 设置时间服务器的服务端名字 s…

ceph log内容解析

log内容构造 如osd的一条log 分别表示 时间戳 线程id 日志等级 子模块 内容实体 剖析源码实现 每条log都是由一个Entry构成 定义在src/log/entry.h中 Entry(short pr, short sub) :m_stamp(clock().now()), // 打印日志时的时间戳m_thread(pthread_self()), // 打印日志的线…

MySQL进阶_11.主从复制

文章目录 一、主从复制概述1.1、如何提升数据库并发能力1.2、主从复制的作用 二、主从复制的原理2.1、原理剖析2.2、原理剖析 一、主从复制概述 1.1、如何提升数据库并发能力 应用对数据库而言都是“ 读多写少 ”&#xff0c;也就说对数据库读取数据的压力比较大&#xff0c;有…

【Android】使用视图绑定ViewBinding来代替findViewById

文章目录 介绍作用用法开启ViewBinding功能自动生成绑定类在Activity中使用访问视图控件 区别 介绍 ViewBinding 是 Android 开发中的一个功能&#xff0c;它简化了访问视图的过程&#xff0c;避免了使用 findViewById 的繁琐步骤。它通过生成与布局文件相对应的绑定类&#xf…

【python基础】组合数据类型:元组、列表、集合、映射

文章目录 一. 序列类型1. 元组类型2. 列表类型&#xff08;list&#xff09;2.1. 列表创建2.2 列表操作2.3. 列表元素遍历 ing元素列表求平均值删除散的倍数 二. 集合类型&#xff08;set&#xff09;三. 映射类型&#xff08;map&#xff09;1. 字典创建2. 字典操作3. 字典遍历…

OV7670寄存器读出0x00或0xFF

文章目录 问题描述原因分析解决方案 问题描述 OV7670的输出图像异常&#xff0c;怀疑寄存器没有正确配置&#xff0c;在SignalTap中观察到SIO_D在读出阶段一直为高或低 寄存器读出0x00 寄存器读出0xFF 原因分析 在确保电源、时钟和读写时序没有问题的情况下&#xff0c;有…

mysql的索引、事务和存储引擎

目录 索引 索引的概念 索引的作用 作用 索引的副作用 创建索引 创建索引的原则和依据 索引的类型 创建索引 查看索引 删除索引 drop 主键索引 普通索引 添加普通索引 唯一索引 添加唯一索引 组合索引 添加组合索引 查询组合索引 全文索引 添加全文索引 …

K12智慧校园智能化解决方案

1. 项目背景 “十三五”期间&#xff0c;教育信息化工作旨在为教育改革发展提供动力与手段&#xff0c;目标是到2020年建成与国家教育现代化发展目标相适应的教育信息化体系。 2. 建设需求 智慧校园系统框架解析与建设目标分析&#xff0c;旨在实现教育信息化目标任务。 3.…

利用双端队列 实现二叉树的非递归的中序遍历

双端队列&#xff1a;双向队列&#xff1a;支持插入删除元素的线性集合。 java官方文档推荐用deque实现栈&#xff08;stack&#xff09;。 pop(): 弹出栈中元素&#xff0c;也就是返回并移除队头元素&#xff0c;等价于removeFirst()&#xff0c;如果队列无元素&#xff0c;则…

QDockWidget

详细描述 QDockWidget 类提供了一个小部件&#xff0c;它可以停靠在QMainWindow内部&#xff0c;也可以作为桌面上的顶级窗口浮动。 QDockWidget 提供了停靠部件的概念&#xff0c;也称为工具调色板或实用窗口。停靠窗口是放置在 中央部件 周围的停靠部件区域中的辅助窗口&am…

多商户商城系统源码解析及直播电商APP开发指南

本篇文章&#xff0c;笔者将详细解析多商户商城系统的源码结构&#xff0c;并提供开发直播电商APP的指南。 一、多商户商城系统源码解析 系统架构设计 多商户商城系统的架构设计通常分为前端、后端和数据库三个部分&#xff1a; 前端 后端 数据库 核心模块分析 多商户商…

SpringMVC源码深度解析(上)

今天&#xff0c;聊聊SpringMVC框架的原理。SpringMVC属于Web框架&#xff0c;它不能单独存在&#xff0c;需要依赖Servlet容器&#xff0c;常用的Servlet容器有Tomcat、Jetty等&#xff0c;这里以Tomcat为例进行讲解。老规矩&#xff0c;先看看本项目的层级结构&#xff1a; 需…

ETAS RTM配置及使用-CPU Load测量/task时间测量/Isr时间测量

文章目录 前言RTM配置RtmControlRtmGeneralRtmMonitorOS配置RTE配置集成与测试初始化主函数函数执行测量测试CPU LoadTask MonitorISR Monitor函数监控总结前言 一般对CPU Load的测量,task及runnable的监控等有两种方案: 1.需要使用带trace功能的调试器,且硬件也需要支持对…

鸿蒙开发 01 实现骰子布局

鸿蒙开发 01 鸿蒙开发 01 实现骰子布局 1、效果2、代码 1、效果 2、代码 Entry Component struct Index {State message: string Hello Worldbuild() {Column() {Row() {Radio({ value: Radio1, group: radioGroup }).checked(false).height(100)Radio({ value: Radio1, grou…

【Linux线程】线程的认识

目录 线程的概念及一些基本理论 线程异常 线程与进程的关系 线程ID、线程控制块 线程的概念及一些基本理论 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列” 。 Linux没有真正意义上的线…