local SceneManager = { currentSceneName = "", targetSceneName = "" } local ASYNC_FINISH_PROGRESS = 0.899 local EMPTY_SCENE_PATH = "assets/scenes/empty_scene.unity" SceneManager.SCENE_NAME = { MAIN_CITY = "app/scene/maincity/maincity_scene", BATTLE = "app/scene/battle/battle_scene", } -- sceneName:目标场景路径,这里是lua的路径,不是资源的路径 -- showLoading:显示指定的加载界面 -- callback:切换完成后的回调 -- immediately:是否立即切换,是的话会直接切换到目标场景,否则的话会创建一个空场景并先切换到空场景,然后垃圾回收,然后再切换到目标场景 -- keepUI:是否关闭所有UI界面 -- preloadList:下一个场景加载完后需要预加载的资源列表 -- closeLoadingCallback:关闭过场动画时的callback function SceneManager:_changeScene(params) local sceneName = params.sceneName or "" if sceneName == "" then return false end -- 正在切换场景中 if self.targetSceneName ~= "" then return false end -- 当前场景就是目标场景 if self.currentSceneName == sceneName then if not params.reloadScene then return false end params.immediately = false end self.params = params self.targetSceneName = sceneName return true end function SceneManager:changeScene(params) if not self:_changeScene(params) then return false end UIManager:disableTouch() UIManager:showLoading(self.params.showLoading, function() self:loadScene() end) return true end function SceneManager:loadScene() if not self.params.keepUI then UIManager:closeAllUI() end UIManager:hideToastAndMessageBox() self.targetScene = require(self.targetSceneName):create(self.params.sceneParams) if self.params.immediately then self:loadSceneABAsync() else self:createEmptyScene(function() self:loadSceneABAsync() end) end end function SceneManager:createEmptyScene(nextStep) local function loadEmptyScene() local realPath = ResourceManager:getSceneLoadPath(EMPTY_SCENE_PATH) local asyncOperation = CS.UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(realPath, CS.LoadSceneMode.Additive) asyncOperation.allowSceneActivation = false self:scheduleGlobal(function() if asyncOperation.progress >= ASYNC_FINISH_PROGRESS then if not asyncOperation.allowSceneActivation then if self.currentScene then self.currentScene:_onClose() end asyncOperation.allowSceneActivation = true end end if asyncOperation.isDone then nextStep() return true end end, 0.01) end if USE_AB then ResourceManager:loadSceneAsync(EMPTY_SCENE_PATH, function() loadEmptyScene() end) else loadEmptyScene() end end function SceneManager:loadSceneABAsync() if USE_AB then local resPath = self.targetScene:getResPath() ResourceManager:loadSceneAsync(resPath, function() self:LoadSceneAsync() end) else self:LoadSceneAsync() end end function SceneManager:LoadSceneAsync() local resPath = self.targetScene:getResPath() local realPath = ResourceManager:getSceneLoadPath(resPath) local asyncOperation = CS.UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(realPath, CS.LoadSceneMode.Additive) asyncOperation.allowSceneActivation = false self:scheduleGlobal(function() if asyncOperation.progress >= ASYNC_FINISH_PROGRESS then if not asyncOperation.allowSceneActivation then if self.params.immediately and self.currentScene then self.currentScene:_onClose() end asyncOperation.allowSceneActivation = true end end if asyncOperation.isDone then self:onLoadSceneFinished() return true end end, 0.01) end function SceneManager:onLoadSceneFinished() local function nextStep() if self.currentScene then local resPath = self.currentScene:getResPath() ResourceManager:unloadScene(resPath) end if not self.params.immediately then ResourceManager:unloadScene(EMPTY_SCENE_PATH) end if self.params.preloadList then local preloadCount = #self.params.preloadList local loadedCount = 0 local function loadCheck( asset ) loadedCount = loadedCount + 1 local ratio = loadedCount / preloadCount if loadedCount >= preloadCount then self:onFinished() end end if preloadCount > 0 then for i, resPath in ipairs(self.params.preloadList) do ResourceManager:asyncLoad(resPath, loadCheck) end else self:onFinished() end else self:onFinished() end end self:garbageCollect(nextStep) end function SceneManager:onFinished() LocalData:save() self.targetScene:_init(self.params.init) if self.targetScene:closeLoadingAuto() then UIManager:closeLoading(self.params.closeLoadingCallback) UIManager:enableTouch() else if self.params.closeLoadingCallback then self.targetScene:addCloseLoadingCallback(self.params.closeLoadingCallback) end end self.currentSceneName = self.targetSceneName self.currentScene = self.targetScene self.targetSceneName = "" self.targetScene = nil local finishCallback = self.params.callback self.params = nil if finishCallback then finishCallback(self.currentScene) end end function SceneManager:getCurrentScene() return self.currentScene end function SceneManager:getCurrentSceneName() return self.currentSceneName end function SceneManager:getIsInMainCityScene() return self.currentSceneName == SceneManager.SCENE_NAME.MAIN_CITY end function SceneManager:garbageCollect(callback) ResourceManager:unloadAllDelayAssets() CS.BF.BFMain.Instance.LuaMgr:LuaEnvFullGC(30000) collectgarbage("collect") local asyncOperation = CS.UnityEngine.Resources.UnloadUnusedAssets() local function onUnloadComplete(opration) asyncOperation:completed("-", onUnloadComplete) if callback then callback() end end asyncOperation:completed("+", onUnloadComplete) end function SceneManager:scheduleGlobal(func, inter) SchedulerManager:scheduleGlobal(func, inter) end function SceneManager:clear() end -- 只有一个场景 function SceneManager:enterMainScene() local scene = "app/scene/main/main_scene" self.mainScene = require(scene):create() self.mainScene:init() self.currentScene = self.mainScene end return SceneManager