using UnityEngine; using System.Collections; using Snxxz.UI; using System; using System.Collections.Generic; using System.IO; public class Launch : MonoBehaviour { static int step = 0; static LaunchStage m_CurrentStage = LaunchStage.None; public static ProgressInfo progressInfo { get; private set; } float timer = 0f; Queue tasks = new Queue(); LaunchTask currentTask = null; bool launchComplete = false; float surplusProgress = 0f; float surplusTime = 0f; void Start() { Application.backgroundLoadingPriority = ThreadPriority.High; ResourcesPath.Instance.Init(); SnxxzGame.Instance.gameObject.name = "__SnxxzGame__"; Screen.sleepTimeout = SleepTimeout.NeverSleep; SDKUtility.Instance.Init(); var builtInAssetCopyTask = new BuiltInAssetCopyTask(); var initSettingTask = new InitSettingTask(); var sdkInitedTask = new SDKInitedTask(); var assetCopyTask = new AssetCopyTask(); var assetDecompressTask = new AssetDecompressTask(); var getVersionInfoTask = new GetVersionInfoTask(); var checkAssetValidTask = new CheckAssetValidTask(); var downLoadAssetTask = new DownLoadAssetTask(); var assetBundleInitTask = new AssetBundleInitTask(); var configInitTask = new ConfigInitTask(); var launchFadeOutTask = new LaunchFadeOutTask(); tasks.Enqueue(builtInAssetCopyTask); tasks.Enqueue(initSettingTask); #if !UNITY_EDITOR tasks.Enqueue(sdkInitedTask); #endif #if UNITY_ANDROID #if !UNITY_EDITOR tasks.Enqueue(assetCopyTask); tasks.Enqueue(assetDecompressTask); #endif tasks.Enqueue(getVersionInfoTask); #endif #if UNITY_IOS tasks.Enqueue(getVersionInfoTask); #if !UNITY_EDITOR tasks.Enqueue(assetCopyTask); #endif #endif tasks.Enqueue(checkAssetValidTask); tasks.Enqueue(downLoadAssetTask); tasks.Enqueue(assetBundleInitTask); tasks.Enqueue(configInitTask); tasks.Enqueue(launchFadeOutTask); CalculateExpectTotalTime(); } void Update() { if (!launchComplete) { if (currentTask == null) { if (tasks.Count > 0) { currentTask = tasks.Dequeue(); currentTask.Begin(); } else { launchComplete = true; } } if (currentTask != null) { currentTask.Update(); } if (currentTask != null && currentTask.done) { currentTask.End(); CalculateExpectTotalTime(); currentTask = null; } if (m_CurrentStage == LaunchStage.DownLoad) { progressInfo = new ProgressInfo(m_CurrentStage, 1, progressInfo.totalProgress, 0f); } else { timer += Time.deltaTime; var progress = progressInfo.totalProgress + surplusProgress * (Time.deltaTime / surplusTime); progress = Mathf.Clamp(progress, 0, 0.98f); var partProgress = 0f; if (currentTask == null) { partProgress = 0f; } else { var temp = currentTask.timer / Mathf.Min(2f, currentTask.duration); step = (int)temp + 1; partProgress = temp - (int)temp; } progressInfo = new ProgressInfo(m_CurrentStage, step, Mathf.Clamp01(progress), partProgress); } } if (launchComplete) { Debug.LogFormat("启动耗时:{0}", timer); progressInfo = new ProgressInfo(m_CurrentStage, 1, 1f, 1f); this.enabled = false; StageLoad.Instance.PushSceneLoadCommand(new StageLoad.StageLoadCommand() { toMapId = 1, toLineId = 0, needEmpty = false, needLoadResource = true, serverType = ServerType.Main, isClientLoadMap = true }); } } void CalculateExpectTotalTime() { surplusTime = 0f; foreach (var item in tasks) { surplusTime += item.expectTime; } surplusProgress = 1 - progressInfo.totalProgress; } public enum LaunchStage { None = 0, SDKInit = 1, AssetCopy = 2, AssetDecompress = 3, ClientVersion = 4, CheckAsset = 5, DownLoad = 6, AssetBundleInit = 7, ConfigInit = 8, Complete = 9, } public abstract class LaunchTask { public float timer { get; protected set; } public float duration { get; protected set; } bool exceptionReported = false; public bool done { get; protected set; } public float progress { get; protected set; } public virtual float expectTime { get; protected set; } protected float outTime = 15f; public abstract void Begin(); public abstract void Update(); public abstract void End(); public void ExceptionReport() { if (!exceptionReported && timer > outTime && !done) { var content = string.Format("任务:{0};网络状态:{1}", this.GetType().Name, Application.internetReachability); ExceptionCatcher.ReportException("游戏启动执行超时!", content); exceptionReported = true; } } } public class BuiltInAssetCopyTask : LaunchTask { bool firstLaunch = false; public override void Begin() { duration = Mathf.Max(0.1f, expectTime); #if UNITY_ANDROID && !UNITY_EDITOR if (!SDKUtility.builtinAssetCopyFinished) { firstLaunch=true; SDKUtility.Instance.CopyOneAsset("builtin_assetbundle.7z"); SDKUtility.Instance.CopyOneAsset("builtin_assetbundle.manifest.7z"); SDKUtility.Instance.CopyOneAsset("builtin/musics.7z"); SDKUtility.Instance.CopyOneAsset("builtin/musics.manifest.7z"); SDKUtility.Instance.CopyOneAsset("builtin/prefabs.7z"); SDKUtility.Instance.CopyOneAsset("builtin/prefabs.manifest.7z"); SDKUtility.Instance.CopyOneAsset("builtin/sprites.7z"); SDKUtility.Instance.CopyOneAsset("builtin/sprites.manifest.7z"); SDKUtility.Instance.CopyOneAsset("builtin/animationclips.7z"); SDKUtility.Instance.CopyOneAsset("builtin/animationclips.manifest.7z"); SDKUtility.Instance.CopyOneAsset("builtin/materials.7z"); SDKUtility.Instance.CopyOneAsset("builtin/materials.manifest.7z"); SDKUtility.Instance.CopyOneAsset("builtin/scriptableobjects.7z"); SDKUtility.Instance.CopyOneAsset("builtin/scriptableobjects.manifest.7z"); SDKUtility.Instance.CopyOneAsset("config/Contact.txt.7z"); SDKUtility.Instance.CopyOneAsset("config/HelpInfo.txt.7z"); SDKUtility.Instance.CopyOneAsset("config/PriorBundle.txt.7z"); SDKUtility.Instance.CopyOneAsset("config/PriorLanguage.txt.7z"); SDKUtility.Instance.CopyOneAsset("config/ApkUpdateUrl.txt.7z"); AssetDeCompressTask.Decompress(ResourcesPath.Instance.ExternalStorePath); LocalSave.SetString("BuiltInAssetCopyCompleted_Android", VersionConfig.Get().version); } #endif #if UNITY_IOS && !UNITY_EDITOR if (!VersionUtility.Instance.InIosAuditTime()) { if (!SDKUtility.builtinAssetCopyFinished) { firstLaunch=true; var targetDirectory = ResourcesPath.Instance.ExternalStorePath; if (!Directory.Exists(targetDirectory)) { Directory.CreateDirectory(targetDirectory); } var fileNames = new List(); var files = new List(); FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "builtin"), files); foreach (var file in files) { var name = Path.GetFileName(file.FullName); fileNames.Add(StringUtility.Contact("builtin", Path.DirectorySeparatorChar, name)); } fileNames.Add("builtin_assetbundle"); fileNames.Add("builtin_assetbundle.manifest"); var configFiles = new List(); FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "config"), configFiles); foreach (var file in configFiles) { var name = Path.GetFileName(file.FullName); fileNames.Add(StringUtility.Contact("config", Path.DirectorySeparatorChar, name)); } foreach (var item in fileNames) { var fromPath = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, item); var toPath = StringUtility.Contact(targetDirectory, item); var destDirectoryName = Path.GetDirectoryName(toPath); if (!Directory.Exists(destDirectoryName)) { Directory.CreateDirectory(destDirectoryName); } File.Copy(fromPath, toPath, true); } LocalSave.SetString("BuiltInAssetCopyCompleted_IOS", VersionConfig.Get().version); } } #endif #if UNITY_EDITOR if (!AssetSource.allFromEditor) { FileExtersion.DirectoryCopy(ResourcesPath.CONFIG_FODLER, ResourcesPath.Instance.StreamingAssetPath + "config"); FileExtersion.DirectoryCopy(ResourcesPath.ResourcesOutPath + "BuiltIn", ResourcesPath.Instance.StreamingAssetPath + "builtin"); } #endif if (!firstLaunch) { done = true; } } public override void End() { if (!AssetSource.builtInFromEditor) { AssetBundleUtility.Instance.InitBuiltInAsset(); } ConfigInitiator.SyncInit(); WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.Launch); AssetBundleUtility.Instance.UnloadAssetBundle("builtin/prefabs", true, false); WindowCenter.Instance.OpenFromLocal(); } public override void Update() { if (done) { return; } if (timer > duration) { done = true; } else { done = false; progress = timer / duration; } timer += Time.deltaTime; } } public class InitSettingTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("InitSettingTask_ExpectTime", 1f); } protected set { LocalSave.SetFloat("InitSettingTask_ExpectTime", value); } } public override void Begin() { ShaderUtility.InitGlobalParams(); SoundPlayer.CreateSoundPlayer(); SoundPlayer.Instance.PlayLoginMusic(); SystemSetting.Instance.SetSoundVolume(SystemSetting.Instance.GetSoundVolume()); SystemSetting.Instance.SetSoundEffect(SystemSetting.Instance.GetSoundEffect()); SystemSetting.Instance.SetGameFps(SystemSetting.Instance.GetGameFps()); SystemSetting.Instance.LetFPSUnLimit(); DebugUtility.Instance.Init(); DebugUtility.Instance.CreateDebugRoot(); GameObjectPoolManager.Instance.gameObject.name = "GameObjectPool"; GameObjectPoolManager.Instance.Initialize(); ExceptionCatcher.Init(); ExceptionCatcher.Catch(); GlobalTimeEvent.Instance.Begin(); PackageRegedit.Init(); done = true; } public override void End() { expectTime = timer; } public override void Update() { timer += Time.deltaTime; } } public class SDKInitedTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("SDKInitedTask_ExpectTime", 1f); } protected set { LocalSave.SetFloat("SDKInitedTask_ExpectTime", value); } } public override void Begin() { m_CurrentStage = LaunchStage.SDKInit; duration = Mathf.Max(0.1f, expectTime); } public override void End() { expectTime = timer; DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); OperationLogCollect.Instance.RecordLauchEvent(1); OperationLogCollect.Instance.RecordEvent(1); var cpu = 2; var memory = 2048; DeviceUtility.GetCpuAndMemory(out cpu, out memory); DebugEx.LogFormat("获得机器信息:cpu {0}----内存 {1}", cpu, memory); } public override void Update() { if (done) { return; } timer += Time.deltaTime; if (SDKUtility.Instance.InitFinished) { done = true; } else { done = false; progress = timer / duration; } ExceptionReport(); } } public class AssetCopyTask : LaunchTask { int completedCount = 0; int totalCount = -1; List copyTasks = new List(); public override float expectTime { get { return LocalSave.GetFloat("AssetCopyTask_ExpectTime", 70f); } protected set { LocalSave.SetFloat("AssetCopyTask_ExpectTime", value); } } public override void Begin() { m_CurrentStage = LaunchStage.AssetCopy; duration = Mathf.Max(0.5f, expectTime); outTime = 50f; #if UNITY_ANDROID && !UNITY_EDITOR switch (VersionConfig.Get().assetAccess) { case InstalledAsset.FullAsset: case InstalledAsset.HalfAsset: case InstalledAsset.IngoreDownLoad: if (!SDKUtility.Instance.AssetCopyFinished) { SDKUtility.Instance.CopyAsset(); done = false; progress = 0f; } else { done = true; } break; case InstalledAsset.NullAsset: done = true; break; } #endif #if UNITY_IOS && !UNITY_EDITOR if (VersionUtility.Instance.versionInfo != null && VersionUtility.Instance.versionInfo.downAsset == 1) { switch (VersionConfig.Get().assetAccess) { case InstalledAsset.FullAsset: case InstalledAsset.HalfAsset: case InstalledAsset.IngoreDownLoad: if (!SDKUtility.Instance.AssetCopyFinished) { copyTasks = new List(); FileExtersion.GetAllDirectoryFileInfos(ResourcesPath.Instance.StreamingAssetPath, copyTasks); for (var i = copyTasks.Count - 1; i >= 0; i--) { var fileInfo = copyTasks[i]; var destPath = fileInfo.FullName.Replace(ResourcesPath.Instance.StreamingAssetPath, ResourcesPath.Instance.ExternalStorePath); if (File.Exists(destPath)) { copyTasks.RemoveAt(i); } } completedCount = 0; totalCount = copyTasks.Count; } if (totalCount > 0) { done = false; progress = 0f; } else { done = true; } break; case InstalledAsset.NullAsset: done = true; break; } } else { done = true; } #endif #if UNITY_EDITOR done = true; #endif } public override void End() { expectTime = timer; DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); #if UNITY_IOS && !UNITY_EDITOR LocalSave.SetString("AssetCopyCompleted_IOS", VersionConfig.Get().version); #endif } public override void Update() { if (done) { return; } timer += Time.deltaTime; #if UNITY_ANDROID && !UNITY_EDITOR if (!SDKUtility.Instance.AssetCopyFinished) { done = false; progress = timer / duration; } else { done = true; } #endif #if UNITY_IOS && !UNITY_EDITOR if (totalCount > 0) { if (completedCount < totalCount) { var fileInfo = copyTasks[0]; var destPath = fileInfo.FullName.Replace(ResourcesPath.Instance.StreamingAssetPath, ResourcesPath.Instance.ExternalStorePath); var destDirectoryName = Path.GetDirectoryName(destPath); if (!Directory.Exists(destDirectoryName)) { Directory.CreateDirectory(destDirectoryName); } DebugEx.LogFormat("拷贝文件:{0}", fileInfo.Name); File.Copy(fileInfo.FullName, destPath, true); copyTasks.RemoveAt(0); completedCount++; done = false; progress = (float)completedCount / totalCount; } else { done = true; } } else { done = true; } #endif ExceptionReport(); } } public class AssetDecompressTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("AssetDecompressTask_ExpectTime", 5f); } protected set { LocalSave.SetFloat("AssetDecompressTask_ExpectTime", value); } } AssetDeCompressTask.DecompressProgress deCompressProgress = null; float waitTimer = 0f; public override void Begin() { m_CurrentStage = LaunchStage.AssetDecompress; duration = Mathf.Max(0.5f, expectTime); if (!AssetDeCompressTask.assetDeCompressCompleted) { deCompressProgress = AssetDeCompressTask.DecompressAync(ResourcesPath.Instance.ExternalStorePath); done = false; } else { done = true; } } public override void End() { AssetDeCompressTask.assetDeCompressVersion = VersionConfig.Get().version; AssetDeCompressTask.Delete7zFiles(ResourcesPath.Instance.ExternalStorePath); } public override void Update() { if (done) { return; } timer += Time.deltaTime; progress = timer / duration; if (deCompressProgress == null || deCompressProgress.done) { waitTimer += Time.deltaTime; if (waitTimer > 2f) { done = true; } } } } public class GetVersionInfoTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("GetVersionInfoTask_ExpectTime", 1f); } protected set { LocalSave.SetFloat("GetVersionInfoTask_ExpectTime", value); } } public override void Begin() { m_CurrentStage = LaunchStage.ClientVersion; duration = Mathf.Max(0.5f, expectTime); #if UNITY_ANDROID if (InGameDownTestUtility.enable || !Application.isEditor) { VersionUtility.Instance.RequestVersionCheck(); done = false; progress = 0f; } else { done = true; } #endif #if UNITY_IOS if (!VersionUtility.Instance.InIosAuditTime()) { VersionUtility.Instance.RequestVersionCheck(); done = false; progress = 0f; } else { done = true; } #endif } public override void End() { expectTime = timer; DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); } public override void Update() { if (done) { return; } timer += Time.deltaTime; if (!VersionUtility.Instance.completed) { done = false; progress = timer / expectTime; } else { done = true; } ExceptionReport(); } } public class CheckAssetValidTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("CheckAssetValidTask_ExpectTime", 3f); } protected set { LocalSave.SetFloat("CheckAssetValidTask_ExpectTime", value); } } public override void Begin() { m_CurrentStage = LaunchStage.CheckAsset; duration = Mathf.Max(0.5f, expectTime); ServerListCenter.Instance.RequestJumpUrl(); OperationLogCollect.Instance.RecordLauchEvent(2); OperationLogCollect.Instance.RecordEvent(2); if (VersionUtility.Instance.NeedDownAsset()) { AssetVersionUtility.GetAssetVersionFile(); done = false; progress = 0f; } else { done = true; } } public override void End() { expectTime = timer; DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); GameNotice.OpenGameNotice(); } public override void Update() { if (done) { return; } timer += Time.deltaTime; if (!AssetVersionUtility.checkAssetCompleted) { done = false; progress = timer / expectTime; } else { done = true; } ExceptionReport(); } } public class DownLoadAssetTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("DownLoadAssetTask_ExpectTime", 3f); } protected set { LocalSave.SetFloat("DownLoadAssetTask_ExpectTime", value); } } public override void Begin() { m_CurrentStage = LaunchStage.DownLoad; outTime = 9999f; duration = Mathf.Max(0.5f, expectTime); if (VersionUtility.Instance.NeedDownAsset()) { if (!AssetVersionUtility.priorAssetDownLoadDone) { AssetVersionUtility.BeginDownLoadTask(true); done = false; progress = 0f; } else { done = true; } } else { done = true; } } public override void End() { expectTime = timer; DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); if (!AssetVersionUtility.unPriorAssetDownLoadDone) { AssetVersionUtility.BeginDownLoadTask(false); } } public override void Update() { if (done) { return; } timer += Time.deltaTime; if (!AssetVersionUtility.priorAssetDownLoadDone) { done = false; progress = 0f; } else { done = true; } ExceptionReport(); } } public class AssetBundleInitTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("AssetBundleInitTask_ExpectTime", 1f); } protected set { LocalSave.SetFloat("AssetBundleInitTask_ExpectTime", value); } } public override void Begin() { m_CurrentStage = LaunchStage.AssetBundleInit; duration = Mathf.Max(0.5f, expectTime); if (!AssetSource.allFromEditor) { AssetBundleUtility.Instance.Sync_LoadAll("ui/prioritywindow"); SnxxzGame.Instance.StartCoroutine(AssetBundleUtility.Instance.Initialize()); SnxxzGame.Instance.StartCoroutine(AssetBundleUtility.Instance.InitalizeUIResources()); done = false; progress = 0f; } else { done = true; } } public override void End() { expectTime = timer; UILoader.LoadWindowAsync("LaunchBackGroundWin", null); DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); } public override void Update() { if (done) { return; } if (AssetBundleUtility.Instance.initialized && AssetBundleUtility.Instance.initializedUIAssetBundle) { done = true; } else { done = false; progress = timer / duration; } ExceptionReport(); } } public class ConfigInitTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("ConfigInitTask_ExpectTime", 10f); } protected set { LocalSave.SetFloat("ConfigInitTask_ExpectTime", value); } } float threshold = 1f; public override void Begin() { m_CurrentStage = LaunchStage.ConfigInit; duration = Mathf.Max(0.5f, expectTime); threshold = Application.platform == RuntimePlatform.WindowsEditor ? 1f : 0.9f; LaunchPostProcess.Instance.Begin(); } public override void End() { expectTime = timer; DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); OperationLogCollect.Instance.RecordLauchEvent(3); OperationLogCollect.Instance.RecordEvent(3); } public override void Update() { if (done) { return; } timer += Time.deltaTime; if (!ConfigInitiator.IsLoginConfigInited) { done = false; progress = timer / duration; } else { done = true; } ExceptionReport(); } } public class LaunchFadeOutTask : LaunchTask { public override float expectTime { get { return LocalSave.GetFloat("LaunchFadeOutTask_ExpectTime", 1f); } protected set { LocalSave.SetFloat("LaunchFadeOutTask_ExpectTime", value); } } public override void Begin() { m_CurrentStage = LaunchStage.Complete; duration = Mathf.Max(0.5f, expectTime); LuaUtility.Instance.Init(); CSharpCallLua.Init(); ShaderUtility.WarmUpAll(); SpeechTranslate.Instance.RequestGetToken(); UI3DModelExhibition.CreateStage(); WindowCenter.Instance.Open(true); var launchWin = WindowCenter.Instance.Get(); if (launchWin != null) { launchWin.FadeOut(); } } public override void End() { expectTime = timer; DebugEx.LogFormat("{0}执行时长:{1};", this.GetType().Name, timer); } public override void Update() { if (done) { return; } timer += Time.deltaTime; if (timer >= 1f) { done = true; } else { done = false; progress = Mathf.Clamp01(timer / expectTime); } ExceptionReport(); } } public class WaitTask : LaunchTask { public WaitTask(float seconds) { expectTime = Mathf.Max(0.1f, seconds); } public override void Begin() { } public override void End() { } public override void Update() { timer += Time.deltaTime; if (timer >= expectTime) { done = true; } else { done = false; progress = Mathf.Clamp01(timer / expectTime); } } } public struct ProgressInfo { public LaunchStage stage; public int step; public float totalProgress; public float partProgress; public ProgressInfo(LaunchStage stage, int step, float totalProgress, float partProgress) { this.stage = stage; this.step = step; this.totalProgress = totalProgress; this.partProgress = partProgress; } } }