Files
Main/Assets/Code/Logic/_Required/GameState/State/SceneLoading/SceneLoadingState.cs
2025-01-25 04:38:09 +08:00

447 lines
17 KiB
C#

using UnityEngine;
using System;
using System.Collections;
using Thousandto.Core.Base;
using Thousandto.Core.Asset;
using Thousandto.Code.Center;
using Thousandto.Cfg.Data;
using Thousandto.Core.Support;
using UnityEngine.SceneManagement;
using PathUtils = UnityEngine.Gonbest.MagicCube.PathUtils;
using CoroutinePool = UnityEngine.Gonbest.MagicCube.CoroutinePool;
using StringUtils = UnityEngine.Gonbest.MagicCube.StringUtils;
using FLogger = UnityEngine.Gonbest.MagicCube.FLogger;
namespace Thousandto.Code.Logic
{
/// <summary>
/// 场景加载类
/// </summary>
public class SceneLoadingState : GameStateBase
{
#region//当前变量
//状态转换控制设置
private LoadingState _loadingState = LoadingState.DEFAULT;
//加载参数
private LoadingArgs _loadingArgs = null;
//目标场景
private GameScene _targetScene = null;
#endregion
#region//属性信息
public GameScene TaregetScene
{
get
{
return _targetScene;
}
}
#endregion
#region//构造函数
public SceneLoadingState(GameStateId id) : base(id)
{ }
#endregion
protected override GameStateId OnGetStateID()
{
return GameStateId.SceneLoading;
}
protected override void OnEnter()
{
_loadingState = LoadingState.DEFAULT;
FrameMonitor.EndProfile();
//FLogger.LogError("Start Loading:"+Time.realtimeSinceStartup);
if (HardwareManager.MemoryInfo != null)
FLogger.LogTime(string.Format("SceneLoadingState Enter:AppUsed:{0},Free:{1}", HardwareManager.MemoryInfo.GetAppUsedMemory(), HardwareManager.MemoryInfo.GetFreeMemory()));
//0做输入检查,以及一些预处理
FLogger.DebugAssert(Arg != null, "SceneLoading OnEnter Arg is NULL");
_loadingArgs = Arg as LoadingArgs;
FLogger.DebugAssert(_loadingArgs != null, "SceneLoading Load param is invalid");
FLogger.DebugAssert(_loadingArgs.MapSetting != null, "SceneLoading MapSetting param is invalid");
if (_loadingArgs == null && _loadingArgs.MapSetting == null)
{
return;
}
//这里有判定的原因是,在选择界面和创建界面,根据玩家的一些基础信息已经对持久化资源进行了设置
if (_loadingArgs.FrontMapID != 0)
{
//设置一些不被清除的资源 -- 并且这里的时LocalPlayer也有可能还没有
GameCenter.GameSceneSystem.SetImmortalInfo(true);
}
//清除场景中的关联的预制
GameCenter.GameSceneSystem.SceneSweepPrefab();
//清除场景远近处理缓存
GameCenter.SceneRestoreSystem.ClearCache();
//只有窗体加载之后才会设置下一个场景
GameCenter.LuaSystem.Adaptor.OpenLoadingForm(() => {
//3.开始加载下一个场景的信息
_loadingState = LoadingState.CheckedUpdate;
});
}
protected override void OnLeave()
{
//_loadingArgs = null;
_loadingState = LoadingState.DEFAULT;
IGameState nextState = GameCenter.GameStateSystem.GetNextState();
if (nextState != null)
{
var next = nextState as GameStateBase;
if (next != null)
{
// 当登出或者重新登录时释放
IGameState state = GameCenter.GameStateSystem.GetCurState();
if (state != null)
{
if (next.GameStateID == GameStateId.Login ||
next.GameStateID == GameStateId.AppUpdateCheck)
{
FLogger.LogTime("OnLeave Next State" + next.GameStateID);
//1.处理声音
//2.处理UI
//3.发送退出游戏的消息
//4.释放数据
GameCenter.GameSceneSystem.StopBGMusic();
ReleaseData();
}
}
}
}
}
protected override bool OnUpdate(float deltaTime)
{
//计时器更新
GameCenter.TimerEventSystem.Update(deltaTime);
switch (_loadingState)
{
case LoadingState.CheckedUpdate: //判断更新
CheckUpdate();
break;
case LoadingState.StartImmortalPreLoad: //开始对持久资源进行预加载处理
ResourcesEx.IsPreLoadState = true;
if (_loadingArgs.FrontMapID <= 0)
{
_loadingState = LoadingState.ImmortalPreLoading;
FLogger.LogTime("ImmortalPreLoading");
//只有选择或创建角色后才会预加载
GameCenter.ImmortalResSystem.StartPreLoadImmort();
}
_loadingState = LoadingState.StartScenePreLoad;
break;
case LoadingState.ImmortalPreLoading: //正在进行对持久资源进行预加载
if (Time.frameCount % 30 == 0)
{
ImmortalLoading();
}
break;
case LoadingState.StartScenePreLoad: //开始场景的预加载处理
ResourcesEx.IsPreLoadState = false;
StartScenePreLoad();
break;
case LoadingState.EndLoading: //加载完毕
_loadingState = LoadingState.DEFAULT;
break;
}
return true;
}
#region//判断更新
//判断是否进行分段更新
private void CheckUpdate()
{
//if (PathUtils.IsStreaming())
//{
// FLogger.LogTime("CheckUpdate");
// //绝对路径,如果不存在,则做分段更新操作
// string filePath = PathUtils.GetStreamingRootPath("/Assets/GameAssets/Resources/Scene/" + _loadingArgs.MapSetting.LevelName + ".unity3d");
// if (!System.IO.File.Exists(filePath) )
// {
// UnityEngine.Debug.LogWarning("场景文件不存在,需要更新: " + filePath);
// _loadingState = LoadingState.CheckedUpdateWait;
// GameCenter.MsgPromptSystem.ShowMsgBox(DeclareMessageString.Get(DeclareMessageString.C_SCENE_LOADING_UPDATE_RES),
// DeclareMessageString.Get(DeclareMessageString.C_MSGBOX_CANCEL),
// DeclareMessageString.Get(DeclareMessageString.C_MSGBOX_OK),
// (_ret) =>
// {
// _loadingState = LoadingState.DEFAULT;
// if (_ret == MsgBoxResultCode.Button2)
// {
// GameCenter.GameSceneSystem.ReturnToUpdate();
// }
// else
// {
// GameCenter.GameSceneSystem.ReturnToLogin();
// }
// }
// );
// }
//}
//切换为加载状态
if (_loadingState == LoadingState.CheckedUpdate)
{
_loadingState = LoadingState.StartImmortalPreLoad;
}
}
//持久资源加载中
private void ImmortalLoading()
{
var sum = GameCenter.ImmortalResSystem.GetPreLoadSum();
if (sum == 0)
{
_loadingState = LoadingState.StartScenePreLoad;
}
else
{
var cur = GameCenter.ImmortalResSystem.GetPreLoadCurrentCount();
if (cur <= 0)
{
_loadingState = LoadingState.StartScenePreLoad;
}
else
{
GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.5f * ((float)cur / (float)sum));
}
}
}
//开始场景加载中
private void StartScenePreLoad()
{
FLogger.LogTime("StartScenePreLoad");
GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.5f);
_loadingState = LoadingState.ScenePreLoading;
//开始切换音乐
GameCenter.GameSceneSystem.PlayBGMusic(_loadingArgs.MapSetting.MapId);
//添加后台更新支持
GameCenter.UpdateSystem.CheckSceneResExist(_loadingArgs.MapSetting.MapId,
() =>
{
//开始加载场景
SceneRootAssetsLoader.LoadSceneAssets(
_loadingArgs.MapSetting.LevelName,
() =>
{
bool isLoadFail = ResourcesEx.DebugUIModel ? true : false;
if (!SceneRootAssetsLoader.CurrSceneBundleExit())
{
//场景下载失败了
isLoadFail = true;
}
//场景加载完毕
_loadingState = LoadingState.ScenePreLoaded;
CoroutinePool.AddTask(
LoadWorldAsync(
_loadingArgs.MapSetting.MapId,
_loadingArgs.MapSetting.Name,
_loadingArgs.MapSetting.LevelName,
_loadingArgs.MapSetting.CameraName,
_loadingArgs.MapSetting.CameraNameNight,
_loadingArgs.LineID,_loadingArgs.Position,
isLoadFail));
});
},
() =>
{
GameCenter.GameSceneSystem.ReturnToLogin();
});
}
private void BackToDefaultMap(bool tologin)
{
int backMapId = 102599;
if (tologin)
{
//返回的是同一张地图 直接返回登录
GameCenter.GameStateSystem.ChangeState((int)GameStateId.RetToLogin, 1);
}
else
{
NetHandler.SendMessage_TransportWorldMap(backMapId, 0);
}
}
#endregion
#region
IEnumerator LoadBaseScene(String name, String levelName)
{
//加载一个中间场景// 清除上一个场景数据
FLogger.LogTime("LoadOffScene!");
SceneManager.LoadScene(AssetConstDefine.SceneOffName);
//GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.5f);
FLogger.LogTime("LoadLevel! : " + levelName);
yield return new WaitForEndOfFrame();
// 加载目标场景
SceneManager.LoadScene(levelName);
yield return new WaitForEndOfFrame();
SceneRootAssetsLoader.ReleaseSceneBundle();
}
// 加载场景
IEnumerator LoadWorldAsync(int id, string name, string levelName, string dayCameraName, string nightCameraName, int lineID, Vector2? position = null, bool isFail = false)
{
try
{
GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.9f);
FLogger.LogTime("Start LoadWorldAsync!");
_loadingState = LoadingState.Loading;
yield return new WaitForEndOfFrame();
//1.开始加载进行物理场景的切换
if (isFail)
{
//直接加载一个空场景
FLogger.LogTime("LoadEmptyScene!");
SceneManager.LoadScene(AssetConstDefine.SceneEmptyName);
yield return new WaitForEndOfFrame();
FLogger.LogTime("空场景加载完成!");
}
else
{
//1.1加载一个中间场景// 清除上一个场景数据
FLogger.LogTime("LoadOffScene!");
SceneManager.LoadScene(AssetConstDefine.SceneOffName);
//yield return SceneManager.LoadSceneAsync(AssetConstDefine.SceneOffName, LoadSceneMode.Single);
yield return new WaitForEndOfFrame();
//1.2加载目标场景
float testTime = Time.realtimeSinceStartup;
FLogger.LogTime("LoadLevel! : " + levelName);
var option = SceneManager.LoadSceneAsync(levelName, LoadSceneMode.Single);
if (option == null)
{
//加载空场景
SceneManager.LoadScene(AssetConstDefine.SceneEmptyName);
yield return new WaitForEndOfFrame();
FLogger.LogTime("空场景加载完成!");
}
else
{
while (!option.isDone && option.progress < 1)
{
yield return new WaitForEndOfFrame();
}
FLogger.LogTime("场景异步加载完成! : " + levelName);
}
//SceneManager.LoadScene(levelName);
}
//1.3删除场景的bundle
SceneRootAssetsLoader.ReleaseSceneBundle();
yield return new WaitForEndOfFrame();
//2.物理场景切换成功后,开始创建逻辑场景
FLogger.LogTime("Create Logic Scene");
//Debug.LogError(string.Format("加载场景花费的时间{0}", Time.realtimeSinceStartup - testTime));
_targetScene = new GameScene();
//加载场景的一些逻辑数据信息--寻路等.
FLogger.LogTime("LoadSingleMapInfo!");
GameCenter.PathFinderSystem.LoadSingleMapInfo(DeclareMapsetting.Get(id));
FLogger.LogTime("LoadSingleMapInfo Finish!");
_targetScene.Load(id, name, levelName, dayCameraName, nightCameraName, false, false);
_targetScene.LineID = lineID;
_targetScene.FrontMapID = _loadingArgs.FrontMapID;
FLogger.LogTime("LogicScene Is Created!");
//加载玩家周围区域物件资源
FLogger.LogTime("Init SceneRestoreSystem !");
if(_targetScene.GetUnitySceneRoot() != null)
GameCenter.SceneRestoreSystem.InitSceneData(_targetScene.GetUnitySceneRoot().gameObject, position);
FLogger.LogTime("SceneRestoreSystem Init Finish !");
yield return new WaitForEndOfFrame();
//3.加载玩家自己的数据
//这里需要判断,如果角色玩家数据为空,表示是第一次登陆游戏
//否则,需要重新加载玩家数据,
if (LocalPlayerRoot.LocalPlayer != null)
{
_targetScene.ReloadLocalPlayer(_loadingArgs.Position);
}
yield return new WaitForEndOfFrame();
FLogger.LogTime("ChangeToState GameStateId.World");
if (_targetScene != null)
{
_targetScene.TransType = _loadingArgs.transType;
_targetScene.TransParam = _loadingArgs.transParam;
}
//OwnerGameCase.ChangeToState(GameStateId.World, _targetScene); // 直接进入world state
GameCenter.GameStateSystem.ChangeState((int)GameStateId.World, _targetScene);
}
finally
{
_targetScene = null;
//恢复网络数据处理, 恢复心跳
//发送一个进入地图成功的消息给服务端
FLogger.LogTime("Client EnteredMap! finally");
}
yield return new WaitForEndOfFrame();
FLogger.LogTime("Client EnteredMap!");
_loadingState = LoadingState.EndLoading;
}
// 删除已加载数据 -- 断线等状态强制转换
private void ReleaseData()
{
try
{
if (_targetScene != null)
{
_targetScene.Unload();
_targetScene = null;
}
GameCenter.GameSceneSystem.SceneSweepPrefab();
GameCenter.GameSceneSystem.SceneSweepAsset();
}
catch (System.Exception ex)
{
FLogger.LogException(ex);
}
}
#endregion
}
}