/// <summary> /// 为挂载 MouseRayTargetBase 的目标添加鼠标左键点击事件 /// </summary> /// <param name="target">目标</param> /// <param name="callback">点击事件回调</param> public static void AddClickListener(this GameObject target, HTFAction callback) { Main.m_Controller.AddClickListener(target, callback); }
/// <summary> /// 取消订阅二型事件 /// </summary> /// <typeparam name="T">事件处理类</typeparam> /// <param name="handler">事件处理者</param> public void Unsubscribe <T>(HTFAction handler) where T : EventHandlerBase { _helper.Unsubscribe(typeof(T), handler); }
/// <summary> /// 创建实体 /// </summary> /// <typeparam name="T">实体逻辑类</typeparam> /// <param name="entityName">实体指定名称(为 <None> 时默认使用实体逻辑类名称)</param> /// <param name="loadingAction">创建实体过程进度回调</param> /// <param name="loadDoneAction">创建实体完成回调</param> /// <returns>加载协程</returns> public Coroutine CreateEntity <T>(string entityName = "<None>", HTFAction <float> loadingAction = null, HTFAction <EntityLogicBase> loadDoneAction = null) where T : EntityLogicBase { return(_helper.CreateEntity(typeof(T), entityName, loadingAction, loadDoneAction)); }
/// <summary> /// 订阅二型事件 /// </summary> /// <param name="type">事件处理类</param> /// <param name="handler">事件处理者</param> public void Subscribe(Type type, HTFAction handler) { _helper.Subscribe(type, handler); }
/// <summary> /// 订阅三型事件 /// </summary> /// <param name="type">事件处理类</param> /// <param name="handler">事件处理者</param> public void Subscribe(Type type, HTFAction <EventHandlerBase> handler) { _helper.Subscribe(type, handler); }
/// <summary> /// 注册对象池 /// </summary> /// <param name="name">对象池名称</param> /// <param name="spawnTem">对象模板</param> /// <param name="onSpawn">对象生成时初始化委托</param> /// <param name="onDespawn">对象回收时处理委托</param> public void RegisterSpawnPool(string name, GameObject spawnTem, HTFAction <GameObject> onSpawn, HTFAction <GameObject> onDespawn) { if (!_spawnPools.ContainsKey(name)) { _spawnPools.Add(name, new ObjectSpawnPool(spawnTem, Limit, onSpawn, onDespawn)); } else { throw new HTFrameworkException(HTFrameworkModule.ObjectPool, "注册对象池失败:已存在对象池 " + name + " !"); } }
/// <summary> /// 返回到主线程 /// </summary> /// <param name="action">返回到主线程执行的操作</param> public void QueueOnMainThread(HTFAction action) { _isCanDoQueue = false; _actionQueue.Add(action); _isCanDoQueue = true; }
/// <summary> /// 语音识别 /// </summary> /// <param name="clip">语音音频</param> /// <param name="handler">识别成功处理者</param> /// <param name="failHandler">识别失败处理者</param> /// <returns>语音识别的协程</returns> public static Coroutine Recognition(AudioClip clip, HTFAction <string> handler, HTFAction failHandler) { if (clip == null) { Log.Error("语音识别失败:语音内容为空!"); return(null); } return(Main.Current.StartCoroutine(RecognitionCoroutine(SpeechUtility.FromAudioClip(clip), handler, failHandler))); }
private static IEnumerator RecognitionCoroutine(byte[] data, HTFAction <string> handler, HTFAction failHandler) { string url = string.Format("{0}?cuid={1}&token={2}", RecognitionAPI, SystemInfo.deviceUniqueIdentifier, TOKEN); WWWForm form = new WWWForm(); form.AddBinaryData("audio", data); using (UnityWebRequest request = UnityWebRequest.Post(url, form)) { request.SetRequestHeader("Content-Type", "audio/pcm;rate=16000"); yield return(request.SendWebRequest()); if (!request.isNetworkError && !request.isHttpError) { JsonData jsonData = GlobalTools.StringToJson(request.downloadHandler.text); if ((int)jsonData["err_no"] == 0) { string text = jsonData["result"].Count > 0 ? jsonData["result"][0].ToString() : "<None>"; handler?.Invoke(text); } else { Log.Error("语音识别失败:" + jsonData["err_msg"].ToString()); failHandler?.Invoke(); } } else { Log.Error("语音识别失败:" + request.responseCode + " " + request.error); failHandler?.Invoke(); } } }
private static IEnumerator WaitExecute(HTFAction action, WaitUntil waitUntil) { yield return(waitUntil); action(); }
private static IEnumerator SynthesisCoroutine(string text, HTFAction <AudioClip> handler, HTFAction failHandler, int timeout, Speaker speaker, int volume, int speed, int pitch) { string url = string.Format("{0}?tex='{1}'&tok={2}&cuid={3}&ctp={4}&lan={5}&spd={6}&pit={7}&vol={8}&per={9}&aue={10}", SynthesisAPI, text, TOKEN, SystemInfo.deviceUniqueIdentifier, 1, "zh", speed, pitch, volume, (int)speaker, 6); using (UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.WAV)) { yield return(request.SendWebRequest()); if (!request.isNetworkError && !request.isHttpError) { AudioClip audioClip = DownloadHandlerAudioClip.GetContent(request); handler?.Invoke(audioClip); } else { Log.Error("合成语音失败:" + request.responseCode + " " + request.error); failHandler?.Invoke(); } } }
/// <summary> /// 等待执行 /// </summary> /// <param name="behaviour">执行者</param> /// <param name="action">执行的代码</param> /// <param name="waitUntil">等待的WaitUntil</param> /// <returns>等待的协程</returns> public static Coroutine WaitExecute(this MonoBehaviour behaviour, HTFAction action, WaitUntil waitUntil) { Coroutine coroutine = behaviour.StartCoroutine(WaitExecute(action, waitUntil)); return(coroutine); }
private static IEnumerator DelayExecute(HTFAction action, float delaySeconds) { yield return(YieldInstructioner.GetWaitForSeconds(delaySeconds)); action(); }
/// <summary> /// 延时执行 /// </summary> /// <param name="behaviour">执行者</param> /// <param name="action">执行的代码</param> /// <param name="delaySeconds">延时的秒数</param> /// <returns>延时的协程</returns> public static Coroutine DelayExecute(this MonoBehaviour behaviour, HTFAction action, float delaySeconds) { Coroutine coroutine = behaviour.StartCoroutine(DelayExecute(action, delaySeconds)); return(coroutine); }
/// <summary> /// 热修复目标方法 /// </summary> /// <param name="action">目标方法</param> /// <returns>修复后的方法</returns> public HTFAction <T> FixMethod <T>(HTFAction <T> action) { return(_helper.FixMethod(action)); }
/// <summary> /// 合成语音 /// </summary> /// <param name="text">合成文本</param> /// <param name="handler">合成完毕后的处理者</param> /// <param name="failHandler">合成失败的处理者</param> /// <param name="timeout">超时时长</param> /// <param name="speaker">发音人</param> /// <param name="volume">音量</param> /// <param name="speed">音速</param> /// <param name="pitch">音调</param> /// <returns>合成语音的协程</returns> public static Coroutine Synthesis(string text, HTFAction <AudioClip> handler, HTFAction failHandler, int timeout = 60000, Speaker speaker = Speaker.DuYaYa, int volume = 15, int speed = 5, int pitch = 5) { if (string.IsNullOrEmpty(text) || text == "" || Encoding.Default.GetByteCount(text) >= 1024) { Log.Error("合成语音失败:文本为空或长度超出了1024字节的限制!"); return(null); } return(Main.Current.StartCoroutine(SynthesisCoroutine(text, handler, failHandler, timeout, speaker, volume, speed, pitch))); }
/// <summary> /// 加载资源(异步) /// </summary> /// <typeparam name="T">资源类型</typeparam> /// <param name="info">资源信息标记</param> /// <param name="loadingAction">加载中事件</param> /// <param name="loadDoneAction">加载完成事件</param> /// <param name="isPrefab">是否是加载预制体</param> /// <param name="parent">预制体加载完成后的父级</param> /// <param name="isUI">是否是加载UI</param> /// <returns>加载协程迭代器</returns> public IEnumerator LoadAssetAsync <T>(ResourceInfoBase info, HTFAction <float> loadingAction, HTFAction <T> loadDoneAction, bool isPrefab, Transform parent, bool isUI) where T : UnityEngine.Object { DateTime beginTime = DateTime.Now; if (_isLoading) { yield return(_loadWait); } _isLoading = true; yield return(Main.Current.StartCoroutine(LoadDependenciesAssetBundleAsync(info.AssetBundleName))); DateTime waitTime = DateTime.Now; UnityEngine.Object asset = null; if (LoadMode == ResourceLoadMode.Resource) { ResourceRequest request = Resources.LoadAsync <T>(info.ResourcePath); while (!request.isDone) { loadingAction?.Invoke(request.progress); yield return(null); } asset = request.asset; if (asset) { if (isPrefab) { asset = ClonePrefab(asset as GameObject, parent, isUI); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "加载资源失败:Resources文件夹中不存在资源 " + info.ResourcePath + "!"); } } else { #if UNITY_EDITOR if (IsEditorMode) { loadingAction?.Invoke(1); yield return(null); asset = AssetDatabase.LoadAssetAtPath <T>(info.AssetPath); if (asset) { if (isPrefab) { asset = ClonePrefab(asset as GameObject, parent, isUI); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "加载资源失败:路径中不存在资源 " + info.AssetPath + "!"); } } else { if (AssetBundles.ContainsKey(info.AssetBundleName)) { loadingAction?.Invoke(1); yield return(null); asset = AssetBundles[info.AssetBundleName].LoadAsset <T>(info.AssetPath); if (asset) { if (isPrefab) { asset = ClonePrefab(asset as GameObject, parent, isUI); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "加载资源失败:AB包 " + info.AssetBundleName + " 中不存在资源 " + info.AssetPath + " !"); } } else { using (UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(AssetBundleRootPath + info.AssetBundleName, GetAssetBundleHash(info.AssetBundleName))) { request.SendWebRequest(); while (!request.isDone) { loadingAction?.Invoke(request.downloadProgress); yield return(null); } if (!request.isNetworkError && !request.isHttpError) { AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request); if (bundle) { asset = bundle.LoadAsset <T>(info.AssetPath); if (asset) { if (isPrefab) { asset = ClonePrefab(asset as GameObject, parent, isUI); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "加载资源失败:AB包 " + info.AssetBundleName + " 中不存在资源 " + info.AssetPath + " !"); } if (IsCacheAssetBundle) { if (!AssetBundles.ContainsKey(info.AssetBundleName)) { AssetBundles.Add(info.AssetBundleName, bundle); } } else { bundle.Unload(false); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "请求:" + request.url + " 未下载到AB包!"); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "请求:" + request.url + " 遇到网络错误:" + request.error + "!"); } } } } #else if (AssetBundles.ContainsKey(info.AssetBundleName)) { loadingAction?.Invoke(1); yield return(null); asset = AssetBundles[info.AssetBundleName].LoadAsset <T>(info.AssetPath); if (asset) { if (isPrefab) { asset = ClonePrefab(asset as GameObject, parent, isUI); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "加载资源失败:AB包 " + info.AssetBundleName + " 中不存在资源 " + info.AssetPath + " !"); } } else { using (UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(AssetBundleRootPath + info.AssetBundleName, GetAssetBundleHash(info.AssetBundleName))) { request.SendWebRequest(); while (!request.isDone) { loadingAction?.Invoke(request.downloadProgress); yield return(null); } if (!request.isNetworkError && !request.isHttpError) { AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request); if (bundle) { asset = bundle.LoadAsset <T>(info.AssetPath); if (asset) { if (isPrefab) { asset = ClonePrefab(asset as GameObject, parent, isUI); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "加载资源失败:AB包 " + info.AssetBundleName + " 中不存在资源 " + info.AssetPath + " !"); } if (IsCacheAssetBundle) { if (!AssetBundles.ContainsKey(info.AssetBundleName)) { AssetBundles.Add(info.AssetBundleName, bundle); } } else { bundle.Unload(false); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "请求:" + request.url + " 未下载到AB包!"); } } else { throw new HTFrameworkException(HTFrameworkModule.Resource, "请求:" + request.url + " 遇到网络错误:" + request.error + "!"); } } } #endif } DateTime endTime = DateTime.Now; Log.Info(string.Format("异步加载资源{0}[{1}模式]:\r\n{2}\r\n等待耗时:{3}秒 加载耗时:{4}秒" , asset ? "成功" : "失败" , LoadMode.ToString() , LoadMode == ResourceLoadMode.Resource ? info.GetResourceFullPath() : info.GetAssetBundleFullPath(AssetBundleRootPath) , (waitTime - beginTime).TotalSeconds , (endTime - waitTime).TotalSeconds)); if (asset) { DataSetInfo dataSet = info as DataSetInfo; if (dataSet != null && dataSet.Data != null) { asset.Cast <DataSetBase>().Fill(dataSet.Data); } loadDoneAction?.Invoke(asset as T); } asset = null; _isLoading = false; }
/// <summary> /// 加载预制体(异步) /// </summary> /// <param name="info">预制体配置信息</param> /// <param name="parent">预制体的预设父物体</param> /// <param name="loadingAction">预制体加载中回调</param> /// <param name="loadDoneAction">预制体加载完成回调</param> /// <param name="isUI">预制体是否是UI</param> /// <returns>加载协程</returns> public Coroutine LoadPrefab(PrefabInfo info, Transform parent, HTFAction <float> loadingAction = null, HTFAction <GameObject> loadDoneAction = null, bool isUI = false) { return(Main.Current.StartCoroutine(LoadAssetAsync(info, loadingAction, loadDoneAction, true, parent, isUI))); }
public ObjectSpawnPool(GameObject spawnTem, int limit, HTFAction <GameObject> onSpawn, HTFAction <GameObject> onDespawn) { _spawnTem = spawnTem; _limit = limit; _onSpawn = onSpawn; _onDespawn = onDespawn; }
/// <summary> /// 加载资源(异步) /// </summary> /// <typeparam name="T">资源类型</typeparam> /// <param name="info">资源配置信息</param> /// <param name="loadingAction">资源加载中回调</param> /// <param name="loadDoneAction">资源加载完成回调</param> /// <returns>加载协程</returns> public Coroutine LoadAsset <T>(AssetInfo info, HTFAction <float> loadingAction = null, HTFAction <T> loadDoneAction = null) where T : UnityEngine.Object { return(Main.Current.StartCoroutine(LoadAssetAsync(info, loadingAction, loadDoneAction))); }
/// <summary> /// 创建实体 /// </summary> /// <param name="type">实体逻辑类</param> /// <param name="entityName">实体指定名称(为 <None> 时默认使用实体逻辑类名称)</param> /// <param name="loadingAction">创建实体过程进度回调</param> /// <param name="loadDoneAction">创建实体完成回调</param> /// <returns>加载协程</returns> public Coroutine CreateEntity(Type type, string entityName, HTFAction <float> loadingAction, HTFAction <EntityLogicBase> loadDoneAction) { EntityResourceAttribute attribute = type.GetCustomAttribute <EntityResourceAttribute>(); if (attribute != null) { if (Entities.ContainsKey(type)) { if (attribute.IsUseObjectPool && ObjectPools[type].Count > 0) { EntityLogicBase entityLogic = GenerateEntity(type, ObjectPools[type].Dequeue(), entityName == "<None>" ? type.Name : entityName); loadingAction?.Invoke(1); loadDoneAction?.Invoke(entityLogic); Main.m_Event.Throw(this, Main.m_ReferencePool.Spawn <EventCreateEntitySucceed>().Fill(entityLogic)); return(null); } else { if (_defineEntities.ContainsKey(type.FullName) && _defineEntities[type.FullName] != null) { EntityLogicBase entityLogic = GenerateEntity(type, Main.Clone(_defineEntities[type.FullName], _entitiesGroup[type].transform), entityName == "<None>" ? type.Name : entityName); loadingAction?.Invoke(1); loadDoneAction?.Invoke(entityLogic); Main.m_Event.Throw(this, Main.m_ReferencePool.Spawn <EventCreateEntitySucceed>().Fill(entityLogic)); return(null); } else { return(Main.m_Resource.LoadPrefab(new PrefabInfo(attribute), _entitiesGroup[type].transform, loadingAction, (obj) => { EntityLogicBase entityLogic = GenerateEntity(type, obj, entityName == "<None>" ? type.Name : entityName); loadDoneAction?.Invoke(entityLogic); Main.m_Event.Throw(this, Main.m_ReferencePool.Spawn <EventCreateEntitySucceed>().Fill(entityLogic)); })); } } } else { throw new HTFrameworkException(HTFrameworkModule.Entity, "创建实体失败:实体对象 " + type.Name + " 并未存在!"); } } return(null); }
/// <summary> /// 加载数据集(异步) /// </summary> /// <typeparam name="T">数据集类型</typeparam> /// <param name="info">数据集配置信息</param> /// <param name="loadingAction">数据集加载中回调</param> /// <param name="loadDoneAction">数据集加载完成回调</param> /// <returns>加载协程</returns> public Coroutine LoadDataSet <T>(DataSetInfo info, HTFAction <float> loadingAction = null, HTFAction <T> loadDoneAction = null) where T : DataSetBase { return(Main.Current.StartCoroutine(LoadAssetAsync(info, loadingAction, loadDoneAction))); }
/// <summary> /// 订阅三型事件 /// </summary> /// <typeparam name="T">事件处理类</typeparam> /// <param name="handler">事件处理者</param> public void Subscribe <T>(HTFAction <EventHandlerBase> handler) where T : EventHandlerBase { _helper.Subscribe(typeof(T), handler); }
/// <summary> /// 注册对象池 /// </summary> /// <param name="name">对象池名称</param> /// <param name="spawnTem">对象模板</param> /// <param name="onSpawn">对象生成时初始化委托</param> /// <param name="onDespawn">对象回收时处理委托</param> /// <param name="limit">对象池上限,等于0时,表示使用默认值</param> public void RegisterSpawnPool(string name, GameObject spawnTem, HTFAction <GameObject> onSpawn, HTFAction <GameObject> onDespawn, int limit) { if (spawnTem == null) { return; } if (!SpawnPools.ContainsKey(name)) { SpawnPools.Add(name, new ObjectSpawnPool(spawnTem, limit <= 0 ? _limit : limit, onSpawn, onDespawn)); } else { Log.Error("注册对象池失败:已存在对象池 " + name + " !"); } }
/// <summary> /// 取消订阅一型事件 /// </summary> /// <param name="type">事件处理类</param> /// <param name="handler">事件处理者</param> public void Unsubscribe(Type type, HTFAction <object, EventHandlerBase> handler) { _helper.Unsubscribe(type, handler); }
/// <summary> /// 热修复目标方法 /// </summary> /// <param name="action">目标方法</param> /// <returns>修复后的方法</returns> public HTFAction <T1, T2, T3> FixMethod <T1, T2, T3>(HTFAction <T1, T2, T3> action) { return(_helper.FixMethod(action)); }
/// <summary> /// 取消订阅事件 /// </summary> /// <typeparam name="T">事件处理类</typeparam> /// <param name="handler">事件处理者</param> public void Unsubscribe <T>(HTFAction <object, EventHandlerBase> handler) where T : EventHandlerBase { Unsubscribe(typeof(T), handler); }
/// <summary> /// 热修复目标方法 /// </summary> /// <param name="action">目标方法</param> /// <returns>修复后的方法</returns> public HTFAction FixMethod(HTFAction action) { return(_helper.FixMethod(action)); }
/// <summary> /// 创建实体 /// </summary> /// <param name="type">实体逻辑类</param> /// <param name="entityName">实体指定名称(为 <None> 时默认使用实体逻辑类名称)</param> /// <param name="loadingAction">创建实体过程进度回调</param> /// <param name="loadDoneAction">创建实体完成回调</param> /// <returns>加载协程</returns> public Coroutine CreateEntity(Type type, string entityName = "<None>", HTFAction <float> loadingAction = null, HTFAction <EntityLogicBase> loadDoneAction = null) { return(_helper.CreateEntity(type, entityName, loadingAction, loadDoneAction)); }
/// <summary> /// 注册对象池 /// </summary> /// <param name="name">对象池名称</param> /// <param name="spawnTem">对象模板</param> /// <param name="onSpawn">对象生成时初始化委托</param> /// <param name="onDespawn">对象回收时处理委托</param> /// <param name="limit">对象池上限,等于0时,表示使用默认值</param> public void RegisterSpawnPool(string name, GameObject spawnTem, HTFAction <GameObject> onSpawn = null, HTFAction <GameObject> onDespawn = null, int limit = 0) { _helper.RegisterSpawnPool(name, spawnTem, onSpawn, onDespawn, limit); }