public TweenNode <T> SetEase(AnimationCurve easeCurve) { if (easeCurve == null) { MotionLog.Error("AnimationCurve is null. Tween ease function use default."); _easeFun = TweenEase.Linear.Default; return(this); } // 获取动画总时长 float length = 0f; for (int i = 0; i < easeCurve.keys.Length; i++) { var key = easeCurve.keys[i]; if (key.time > length) { length = key.time; } } _easeFun = delegate(float t, float b, float c, float d) { float time = length * (t / d); return(easeCurve.Evaluate(time) * c + b); }; return(this); }
public AssetConfig LoadConfig(Type configType, string location) { string configName = configType.FullName; // 防止重复加载 if (_configs.ContainsKey(configName)) { MotionLog.Error($"Config {configName} is already existed."); return(null); } AssetConfig config; if (ActivatorServices != null) { config = ActivatorServices.CreateInstance(configType) as AssetConfig; } else { config = Activator.CreateInstance(configType) as AssetConfig; } if (config == null) { MotionLog.Error($"Config {configName} create instance failed."); } else { config.Load(location); _configs.Add(configName, config); } return(config); }
private void Handle_Completed(AssetOperationHandle obj) { try { TextAsset txt = _handle.AssetObject as TextAsset; if (txt != null) { // 解析数据 ParseDataInternal(txt.bytes); } } catch (Exception ex) { MotionLog.Error($"Failed to parse config {Location}. Error : {ex.ToString()}"); } // 注意:为了节省内存这里立即释放了资源 if (_assetRef != null) { _assetRef.Release(); _assetRef = null; } IsPrepare = true; _userCallback?.Invoke(this); }
/// <summary> /// 转换节点 /// </summary> public void Transition(string nodeName) { if (string.IsNullOrEmpty(nodeName)) { throw new ArgumentNullException(); } IFsmNode node = GetNode(nodeName); if (node == null) { MotionLog.Error($"Can not found node {nodeName}"); return; } // 检测转换关系 if (Graph != null) { if (Graph.CanTransition(_curNode.Name, node.Name) == false) { MotionLog.Error($"Can not transition {_curNode} to {node}"); return; } } MotionLog.Log($"Transition {_curNode.Name} to {node.Name}"); _preNode = _curNode; _curNode.OnExit(); _curNode = node; _curNode.OnEnter(); }
/// <summary> /// 处理连接请求 /// </summary> private void ProcessConnected(object obj) { SocketAsyncEventArgs e = obj as SocketAsyncEventArgs; UserToken token = (UserToken)e.UserToken; if (e.SocketError == SocketError.Success) { if (_channel != null) { throw new Exception("TcpClient channel is created."); } // 创建频道 _channel = new TcpChannel(); _channel.InitChannel(_syncContext, e.ConnectSocket, _packageCoderType, _packageBodyMaxSize); } else { MotionLog.Error($"Network connecte error : {e.SocketError}"); } // 回调函数 if (token.Callback != null) { token.Callback.Invoke(e.SocketError); } }
/// <summary> /// 接收事件 /// </summary> public void HandleEventMessage(IEventMessage msg) { if (msg is PatchEventMessageDefine.OperationEvent) { var message = msg as PatchEventMessageDefine.OperationEvent; if (message.operation == EPatchOperation.BeginingDownloadWebFiles) { // 从挂起的地方继续 if (_procedure.Current == EPatchStates.GetDonwloadList.ToString()) { _procedure.SwitchNext(); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else if (message.operation == EPatchOperation.TryRequestGameVersion) { // 修复当前节点错误 if (_procedure.Current == EPatchStates.RequestGameVersion.ToString()) { _procedure.Switch(_procedure.Current); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else if (message.operation == EPatchOperation.TryDownloadWebPatchManifest) { // 修复当前节点错误 if (_procedure.Current == EPatchStates.GetWebPatchManifest.ToString()) { _procedure.Switch(_procedure.Current); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else if (message.operation == EPatchOperation.TryDownloadWebFiles) { // 修复当前节点错误 if (_procedure.Current == EPatchStates.DownloadWebFiles.ToString()) { _procedure.Switch(EPatchStates.GetDonwloadList.ToString()); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else { throw new NotImplementedException($"{message.operation}"); } } }
/// <summary> /// 捕获异常错误 /// </summary> public void HandleError(bool isDispose, string error) { MotionLog.Error(error); if (isDispose) { Dispose(); } }
/// <summary> /// 获取配表 /// </summary> public AssetConfig GetConfig(string configName) { if (_configs.ContainsKey(configName)) { return(_configs[configName]); } MotionLog.Error($"Not found config {configName}"); return(null); }
/// <summary> /// 获取资源包名称 /// </summary> public string GetAssetBundleName(string assetPath) { if (AssetsMap.TryGetValue(assetPath, out PatchElement value)) { return(value.BundleName); } else { MotionLog.Error($"Not found asset in patch manifest: {assetPath}"); return(string.Empty); } }
public AssetConfig GetConfig(Type configType) { foreach (var pair in _configs) { if (pair.Value.GetType() == configType) { return(pair.Value); } } MotionLog.Error($"Not found config {configType.Name}"); return(null); }
/// <summary> /// 启动状态机 /// </summary> /// <param name="entryNode">入口节点</param> public void Run(string entryNode) { _curNode = GetNode(entryNode); _preNode = GetNode(entryNode); if (_curNode != null) { _curNode.OnEnter(); } else { MotionLog.Error($"Not found entry node : {entryNode}"); } }
public AssetConfig GetConfig(Type configType) { string configName = configType.FullName; foreach (var pair in _configs) { if (pair.Key == configName) { return(pair.Value); } } MotionLog.Error($"Not found config {configName}"); return(null); }
/// <summary> /// 同步加载接口 /// 注意:仅支持无依赖关系的资源 /// </summary> public T SyncLoad <T>(string location, string variant) where T : UnityEngine.Object { UnityEngine.Object result = null; if (AssetSystem.SimulationOnEditor) { #if UNITY_EDITOR string loadPath = AssetPathHelper.FindDatabaseAssetPath(location); result = UnityEditor.AssetDatabase.LoadAssetAtPath <T>(loadPath); if (result == null) { MotionLog.Error($"Failed to load {loadPath}"); } #else throw new Exception($"AssetSystem virtual simulation only support unity editor."); #endif } else { if (AssetSystem.BundleServices == null) { throw new Exception($"{nameof(AssetSystem.BundleServices)} is null."); } string manifestPath = AssetSystem.BundleServices.ConvertLocationToManifestPath(location, variant); string loadPath = AssetSystem.BundleServices.GetAssetBundleLoadPath(manifestPath); AssetBundle bundle = AssetBundle.LoadFromFile(loadPath); if (bundle != null) { string fileName = System.IO.Path.GetFileName(location); result = bundle.LoadAsset <T>(fileName); } if (result == null) { MotionLog.Error($"Failed to load {loadPath}"); } if (bundle != null) { bundle.Unload(false); } } return(result as T); }
/// <summary> /// 处理接收请求 /// </summary> private void ProcessAccept(object obj) { SocketAsyncEventArgs e = obj as SocketAsyncEventArgs; if (e.SocketError == SocketError.Success) { // 创建频道 TcpChannel channel = new TcpChannel(); channel.InitChannel(e.AcceptSocket, _packageCoderType, _packageMaxSize); // 加入到频道列表 lock (_allChannels) { _allChannels.Add(channel); } } else { MotionLog.Error($"ProcessAccept error : {e.SocketError}"); } // 投递下一个接收请求 StartAccept(e); }
protected override void OnAssetLoad(GameObject go) { var desktopTrans = Go.transform.BFSearch("UIDesktop"); if (desktopTrans != null) { UIDesktop = desktopTrans.gameObject; } else { MotionLog.Error("Not found UIDesktop gameObject in UIRoot"); } var cameraTrans = Go.transform.BFSearch("UICamera"); if (cameraTrans != null) { UICamera = cameraTrans.GetComponent <Camera>(); } else { MotionLog.Error("Not found UICamera gameObject in UIRoot"); } }
/// <summary> /// 更新下载器 /// </summary> public void Update() { if (DownloadStates != EDownloaderStates.Loading) { return; } // 检测下载器结果 _removeList.Clear(); long downloadBytes = CurrentDownloadBytes; foreach (var loader in _downloaders) { downloadBytes += (long)loader.DownloadedBytes; if (loader.IsDone() == false) { continue; } PatchBundle patchBundle = loader.UserData as PatchBundle; // 检测是否下载失败 if (loader.HasError()) { loader.ReportError(); loader.Dispose(); _removeList.Add(loader); _loadFailedList.Add(patchBundle); continue; } // 验证下载文件完整性 if (_patcherMgr.CheckContentIntegrity(patchBundle) == false) { MotionLog.Error($"Check download content integrity is failed : {patchBundle.BundleName}"); loader.Dispose(); _removeList.Add(loader); _checkFailedList.Add(patchBundle); continue; } // 下载成功 loader.Dispose(); _removeList.Add(loader); _succeedList.Add(patchBundle); CurrentDownloadCount++; CurrentDownloadBytes += patchBundle.SizeBytes; } // 移除已经完成的下载器(无论成功或失败) foreach (var loader in _removeList) { _downloaders.Remove(loader); } // 如果下载进度发生变化 if (_lastDownloadBytes != downloadBytes || _lastDownloadCount != CurrentDownloadCount) { _lastDownloadBytes = downloadBytes; _lastDownloadCount = CurrentDownloadCount; OnDownloadProgressCallback?.Invoke(TotalDownloadCount, _lastDownloadCount, TotalDownloadBytes, _lastDownloadBytes); } // 动态创建新的下载器到最大数量限制 // 注意:如果期间有下载失败的文件,暂停动态创建下载器 if (_downloadList.Count > 0 && _loadFailedList.Count == 0 && _checkFailedList.Count == 0) { if (_downloaders.Count < _maxNumberOnLoad) { int index = _downloadList.Count - 1; WebFileRequest downloader = CreateDownloader(_downloadList[index]); _downloaders.Add(downloader); _downloadList.RemoveAt(index); } } // 下载结算 if (_downloaders.Count == 0) { // 更新缓存并保存 if (_succeedList.Count > 0) { _patcherMgr.CacheDownloadPatchFiles(_succeedList); } if (_loadFailedList.Count > 0) { DownloadStates = EDownloaderStates.Failed; OnPatchFileDownloadFailedCallback?.Invoke(_loadFailedList[0].BundleName); OnDownloadOverCallback?.Invoke(false); } else if (_checkFailedList.Count > 0) { DownloadStates = EDownloaderStates.Failed; OnPatchFileCheckFailedCallback?.Invoke(_checkFailedList[0].BundleName); OnDownloadOverCallback?.Invoke(false); } else { // 结算成功 DownloadStates = EDownloaderStates.Succeed; OnDownloadOverCallback?.Invoke(true); } } }
/// <summary> /// 处理请求操作 /// </summary> public void HandleOperation(EPatchOperation operation) { if (operation == EPatchOperation.BeginGetDownloadList) { // 从挂起的地方继续 if (_procedure.Current == EPatchStates.RequestPatchManifest.ToString()) { _procedure.SwitchNext(); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else if (operation == EPatchOperation.BeginDownloadWebFiles) { // 从挂起的地方继续 if (_procedure.Current == EPatchStates.GetDownloadList.ToString()) { _procedure.SwitchNext(); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else if (operation == EPatchOperation.TryRequestGameVersion) { // 修复当前错误节点 if (_procedure.Current == EPatchStates.RequestGameVersion.ToString()) { _procedure.Switch(_procedure.Current); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else if (operation == EPatchOperation.TryRequestPatchManifest) { // 修复当前错误节点 if (_procedure.Current == EPatchStates.RequestPatchManifest.ToString()) { _procedure.Switch(_procedure.Current); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else if (operation == EPatchOperation.TryDownloadWebFiles) { // 修复当前错误节点 if (_procedure.Current == EPatchStates.DownloadWebFiles.ToString()) { _procedure.Switch(EPatchStates.GetDownloadList.ToString()); } else { MotionLog.Error($"Patch states is incorrect : {_procedure.Current}"); } } else { throw new NotImplementedException($"{operation}"); } }
public override void Update() { // 如果资源文件加载完毕 if (States == ELoaderStates.Success || States == ELoaderStates.Fail) { UpdateAllProvider(); return; } if (States == ELoaderStates.None) { // 检测加载地址是否为空 if (string.IsNullOrEmpty(BundleInfo.LocalPath)) { States = ELoaderStates.Fail; return; } if (string.IsNullOrEmpty(BundleInfo.RemoteURL)) { States = ELoaderStates.CheckDepends; } else { States = ELoaderStates.Download; } } // 1. 从服务器下载 if (States == ELoaderStates.Download) { _downloader = new WebFileRequest(BundleInfo.RemoteURL, BundleInfo.LocalPath); _downloader.DownLoad(); States = ELoaderStates.CheckDownload; } // 2. 检测服务器下载结果 if (States == ELoaderStates.CheckDownload) { if (_downloader.IsDone() == false) { return; } if (_downloader.HasError()) { _downloader.ReportError(); States = ELoaderStates.Fail; } else { // 校验文件完整性 if (AssetSystem.BundleServices.CheckContentIntegrity(BundleInfo.BundleName) == false) { MotionLog.Error($"Check download content integrity is failed : {BundleInfo.BundleName}"); States = ELoaderStates.Fail; } else { States = ELoaderStates.CheckDepends; } } // 释放网络资源下载器 if (_downloader != null) { _downloader.Dispose(); _downloader = null; } } // 3. 检测所有依赖完成状态 if (States == ELoaderStates.CheckDepends) { foreach (var dpLoader in _depends) { if (dpLoader.IsDone() == false) { return; } } States = ELoaderStates.LoadFile; } // 4. 加载AssetBundle if (States == ELoaderStates.LoadFile) { #if UNITY_EDITOR // 注意:Unity2017.4编辑器模式下,如果AssetBundle文件不存在会导致编辑器崩溃,这里做了预判。 if (System.IO.File.Exists(BundleInfo.LocalPath) == false) { MotionLog.Warning($"Not found assetBundle file : {BundleInfo.LocalPath}"); States = ELoaderStates.Fail; return; } #endif // Load assetBundle file if (BundleInfo.IsEncrypted) { if (AssetSystem.DecryptServices == null) { throw new Exception($"{nameof(AssetBundleLoader)} need IDecryptServices : {BundleInfo.BundleName}"); } EDecryptMethod decryptType = AssetSystem.DecryptServices.DecryptType; if (decryptType == EDecryptMethod.GetDecryptOffset) { ulong offset = AssetSystem.DecryptServices.GetDecryptOffset(BundleInfo); _cacheRequest = AssetBundle.LoadFromFileAsync(BundleInfo.LocalPath, 0, offset); } else if (decryptType == EDecryptMethod.GetDecryptBinary) { byte[] binary = AssetSystem.DecryptServices.GetDecryptBinary(BundleInfo); _cacheRequest = AssetBundle.LoadFromMemoryAsync(binary); } else { throw new NotImplementedException($"{decryptType}"); } } else { _cacheRequest = AssetBundle.LoadFromFileAsync(BundleInfo.LocalPath); } States = ELoaderStates.CheckFile; } // 5. 检测AssetBundle加载结果 if (States == ELoaderStates.CheckFile) { if (_cacheRequest.isDone == false) { return; } CacheBundle = _cacheRequest.assetBundle; // Check error if (CacheBundle == null) { MotionLog.Warning($"Failed to load assetBundle file : {BundleInfo.BundleName}"); States = ELoaderStates.Fail; } else { States = ELoaderStates.Success; } } }
private IEnumerator Download() { // 注意:开发者需要在下载前检测磁盘空间不足 // 计算下载文件的总大小 int totalDownloadCount = _patcher.DownloadList.Count; long totalDownloadSizeBytes = 0; foreach (var element in _patcher.DownloadList) { totalDownloadSizeBytes += element.SizeBytes; } // 开始下载列表里的所有资源 MotionLog.Log($"Begine download web files : {_patcher.DownloadList.Count}"); long currentDownloadSizeBytes = 0; int currentDownloadCount = 0; foreach (var element in _patcher.DownloadList) { // 注意:资源版本号只用于确定下载路径 string url = _patcher.GetWebDownloadURL(element.Version.ToString(), element.Name); string savePath = AssetPathHelper.MakePersistentLoadPath(element.Name); element.SavePath = savePath; FileUtility.CreateFileDirectory(savePath); // 创建下载器 WebFileRequest download = new WebFileRequest(url, savePath); yield return(download.DownLoad()); //文件依次加载(在一个文件加载完毕后加载下一个) MotionLog.Log($"Web file is download : {savePath}"); // 检测是否下载失败 if (download.States != EWebRequestStates.Success) { PatchEventDispatcher.SendWebFileDownloadFailedMsg(url, element.Name); yield break; } // 立即释放加载器 download.Dispose(); currentDownloadCount++; currentDownloadSizeBytes += element.SizeBytes; PatchEventDispatcher.SendDownloadFilesProgressMsg(totalDownloadCount, currentDownloadCount, totalDownloadSizeBytes, currentDownloadSizeBytes); } // 验证下载文件的大小 if (_patcher.CheckLevel == ECheckLevel.CheckSize) { foreach (var element in _patcher.DownloadList) { long fileSize = FileUtility.GetFileSize(element.SavePath); if (fileSize != element.SizeBytes) { MotionLog.Error($"Web file size check failed : {element.Name}"); PatchEventDispatcher.SendWebFileCheckFailedMsg(element.Name); yield break; } } } // 验证下载文件的MD5 if (_patcher.CheckLevel == ECheckLevel.CheckMD5) { foreach (var element in _patcher.DownloadList) { string md5 = HashUtility.FileMD5(element.SavePath); if (md5 != element.MD5) { MotionLog.Error($"Web file md5 check failed : {element.Name}"); PatchEventDispatcher.SendWebFileCheckFailedMsg(element.Name); yield break; } } } // 最后清空下载列表 _patcher.DownloadList.Clear(); _patcher.SwitchNext(); }
/// <summary> /// 更新下载器 /// </summary> public void Update() { if (DownloadStates != EDownloaderStates.Loading) { return; } // 检测下载器结果 for (int i = _loaders.Count - 1; i >= 0; i--) { var loader = _loaders[i]; if (loader.IsDone() == false) { continue; } PatchBundle element = loader.UserData as PatchBundle; // 检测是否下载失败 if (loader.HasError()) { loader.ReportError(); loader.Dispose(); _loaders.RemoveAt(i); _loadFailedList.Add(element); continue; } // 验证下载文件完整性 if (_patcher.CheckContentIntegrity(element) == false) { MotionLog.Error($"Check download content integrity is failed : {element.BundleName}"); loader.Dispose(); _loaders.RemoveAt(i); _checkFailedList.Add(element); continue; } // 下载成功 loader.Dispose(); _loaders.RemoveAt(i); _succeedList.Add(element); CurrentDownloadCount++; CurrentDownloadBytes += element.SizeBytes; OnPatchFileDownloadSucceedCallback?.Invoke(TotalDownloadCount, CurrentDownloadCount, TotalDownloadBytes, CurrentDownloadBytes); } // 动态创建新的下载器到最大数量限制 // 注意:如果期间有下载失败的文件,暂停动态创建下载器 if (_downloadList.Count > 0 && _loadFailedList.Count == 0 && _checkFailedList.Count == 0) { if (_loaders.Count < _maxNumberOnLoad) { int index = _downloadList.Count - 1; WebFileRequest downloader = CreateDownloader(_downloadList[index]); _loaders.Add(downloader); _downloadList.RemoveAt(index); } } // 下载结算 if (_loaders.Count == 0) { // 更新缓存并保存 if (_succeedList.Count > 0) { _patcher.CacheDownloadPatchFiles(_succeedList); } if (_loadFailedList.Count > 0) { DownloadStates = EDownloaderStates.Failed; OnPatchFileDownloadFailedCallback?.Invoke(_loadFailedList[0].BundleName); } else if (_checkFailedList.Count > 0) { DownloadStates = EDownloaderStates.Failed; OnPatchFileCheckFailedCallback?.Invoke(_checkFailedList[0].BundleName); } else { // 结算成功 DownloadStates = EDownloaderStates.Succeed; } } }