IEnumerator LoadDropIcon(uint iconId, Sprite3DEx sprite3D, uint loadId) { sprite3D.RenderEnable = false; SGameEngine.AssetResource ar = new SGameEngine.AssetResource(); IconInfo info = GoodsHelper.GetIconInfo(iconId); var iconPath = info.MainTexturePath; yield return(xc.MainGame.GetGlobalMono().StartCoroutine(SGameEngine.ResourceLoader.Instance.load_asset(iconPath, typeof(Texture), ar))); // 检查资源 var tex = ar.asset_ as Texture; if (tex == null) { GameDebug.LogError("LoadDropIcon is failed"); yield break; } // 检查loadId是否变化/sprite3D组件 if (loadId != mCurLoadIconID || sprite3D == null) { ar.destroy(); yield break; } mDropIconRes = ar; sprite3D.SetTexture(tex, iconPath); sprite3D.UVOffset = info.IconRect; sprite3D.RenderEnable = true; }
//-------------------------------------------- // 外部接口 //-------------------------------------------- /// <summary> /// 将某个资源托管到某个gameobject上,当这个gameobject没有了,自动释放托管在上面的这个资源 /// </summary> public void host_res_to_gameobj(GameObject _go, AssetResource _res) { HostResInfo hri = new HostResInfo(); hri.game_obj_ = _go; hri.res_ = _res; lst_host_res_inf_.Add(hri); }
public void Destroy() { if (mIsBossChip && CanPick) { OnTouchExit(); } mDropInfo = null; mDropType = EDropType.None; mCanPick = false; CanNotPickReason = 0; mPickSqrRadius = 0f; mIsTouching = false; if (mTimer != null) { mTimer.Destroy(); mTimer = null; } if (mDisappearTimer != null) { mDisappearTimer.Destroy(); mDisappearTimer = null; } ClearCD(); InstanceDropManager.GetInstance().RemoveDrop(this); if (mDropIconRes != null) { mDropIconRes.destroy(); mDropIconRes = null; } if (mAutoPickCoroutine != null) { mAutoPickCoroutine.Stop(); mAutoPickCoroutine = null; } mDropGoodsSubType = 0; mIsBossChip = false; if (mBossChipEffectGameObject != null) { GameObject.DestroyImmediate(mBossChipEffectGameObject); mBossChipEffectGameObject = null; } mCurLoadEffectID = 0; mCurLoadIconID = 0; m_IsDestory = true; }
private IEnumerator LoadAssetImpl(string asset_path, System.Action <AssetResource> call_back) { AssetResource ar = new AssetResource(); yield return(StartCoroutine(load_asset(asset_path, typeof(UnityEngine.Object), ar, false, false, string.Empty))); if (call_back != null) { call_back(ar); } }
static void ShaderFinishLoad(SGameEngine.AssetResource asset) { if (asset != null && asset.asset_ != null) { m_default_shader = asset.asset_ as Shader; m_default_mat.shader = m_default_shader; } else { m_default_shader = null; } }
private IEnumerator CoLoadNavmeshFile(string path) { SGameEngine.AssetResource result = new SGameEngine.AssetResource(); yield return(MainGame.HeartBehavior.StartCoroutine(SGameEngine.ResourceLoader.Instance.load_asset(path, typeof(TextAsset), result))); // 加载好的数据是否是当前场景的数据 uint stage_id = SceneHelp.GetFirstStageId(SceneHelp.Instance.CurSceneID); uint map_id = SceneHelp.GetMapIdByStageId(stage_id); string navmesh_file = "Assets/Res/NavMesh/" + map_id.ToString() + ".txt"; if (navmesh_file.Equals(path) == false) { yield break; } if (result.asset_ == null) { IsLoadingNavmeshFile = false; yield break; } TextAsset textAsset = result.asset_ as TextAsset; if (textAsset == null || textAsset.text == null) { IsLoadingNavmeshFile = false; Debug.LogError("LevelManager::CoLoadNavmeshFile, can not read navmesh file:" + path); yield break; } bool ret = XNavMesh.LoadBuffer(textAsset.bytes); if (!ret) { mCurNavmeshFile = string.Empty; GameDebug.LogError("navmesh LoadBuffer error : " + path); } else { mCurNavmeshFile = path; } result.destroy(); IsLoadingNavmeshFile = false; }
/// <summary> /// 将_asset中的Object实例化成GameObject /// 实例化后并增加AssetResource的引用计数 /// </summary> public GameObject instantiate_prefab_from_asset_object(AssetResource _asset, Transform parent = null) { AssetObject ao = _asset.get_obj(); GameObject go = null; if (parent != null) { go = GameObject.Instantiate(ao.get_obj_, parent) as GameObject; } else { go = GameObject.Instantiate(ao.get_obj_) as GameObject; } ao.add_ref(); dic_gameobj_asset_.Add(new xc.Tuple <GameObject, AssetObject>(go, ao)); return(go); }
//************************************ // Method: preload an asset, and keep in the cache for some seconds, sothat you can load it quickly without loading from bundle next time //Return IEnumerator : when the iemurrator ends, the asset loaded //Paramater string _asset_path: the asset path. eg. "Assets/Art/a.mat" //Paramater int _life_time: the time(in seconds) this asset keep in cache, it will be asured during this time, the asset will not destroyed from cache. a negitive (< 0 ) value implies infinite. //************************************ public IEnumerator preload(string _asset_path, int _life_time = 30) { if (is_destroyed_) { yield break; } AssetResource ar = new AssetResource(); yield return(StartCoroutine(load_asset(_asset_path, typeof(UnityEngine.Object), ar))); if (_life_time > 0) { yield return(new WaitForSeconds(_life_time)); ar.destroy(); } // <0 = forever ! }
private IEnumerator ReloadRoutine() { var assetRes = new SGameEngine.AssetResource(); yield return(StartCoroutine(SGameEngine.ResourceLoader.Instance.load_asset("Assets/" + xc.ResPath.path3, typeof(TextAsset), assetRes, true, false, string.Empty))); var asset = assetRes.asset_ as TextAsset; if (asset == null) { GameDebug.LogError("ReloadRoutine load_asset failed."); yield break; } var mgr = LuaScriptMgr.Instance; mgr.ReloadBytes(asset.bytes); assetRes.destroy(); }
/// <summary> /// 协程加载关卡配置 /// </summary> /// <param name="path"></param> /// <returns></returns>\ private IEnumerator CoLoadLevelFile(string path) { SGameEngine.AssetResource result = new SGameEngine.AssetResource(); yield return(MainGame.HeartBehavior.StartCoroutine(SGameEngine.ResourceLoader.Instance.load_asset(path, typeof(TextAsset), result))); if (result.asset_ == null) { yield break; } TextAsset textAsset = result.asset_ as TextAsset; if (textAsset == null || textAsset.text == null) { result.destroy(); Debug.LogError("LevelManager::CoLoadLevelFile, can not read level file:" + path); yield break; } Neptune.Data data = new Neptune.Data(); FullSerializer.fsData fsdata = FullSerializer.fsJsonParser.Parse(textAsset.text); var serializer = new FullSerializer.fsSerializer(); var processor = new Neptune.FileSerializerProcessor(); serializer.AddProcessor(processor); serializer.TryDeserialize <Neptune.Data>(fsdata, ref data); if (data == null) { result.destroy(); yield break; } OnLevelLoadFinished(data); ObjCachePoolMgr.Instance.RecycleCSharpObject(data, ObjCachePoolType.JSON, path); result.destroy(); }
/// <summary> /// 加载ai对应的文件 /// </summary> /// <param name="aiFile"></param> /// <returns></returns> private IEnumerator LoadAIFile(string aiFile) { SGameEngine.AssetResource result = new SGameEngine.AssetResource(); string path = string.Format(AI_PATH_PREFIX + "/{0}", aiFile); yield return(MainGame.HeartBehavior.StartCoroutine(SGameEngine.ResourceLoader.Instance.load_asset(path, typeof(TextAsset), result))); if (result.asset_ == null) { GameDebug.LogError("BehaviourAI::LoadAIFile, read ai file error 1:" + aiFile); yield break; } TextAsset textAsset = result.asset_ as TextAsset; if (textAsset == null) { Debug.LogError("BehaviourAI::LoadAIFile,can not read ai file:" + aiFile); yield break; } var options = MiniJSON.JsonDecode(textAsset.text) as Hashtable; if (options == null) { result.destroy(); yield break; } var behaviourTree = new BehaviourTree.BehaviourTree(aiFile, options, this); ObjCachePoolMgr.Instance.RecycleCSharpObject(options, ObjCachePoolType.AIJSON, aiFile); SetBehaviourTree(behaviourTree); result.destroy(); }
static void MatFinishLoad(SGameEngine.AssetResource asset) { m_is_loading_mat = false; if (asset != null && asset.asset_ != null) { m_default_mat = asset.asset_ as Material; if (m_default_mat != null) { string shader_name = ""; #if UNITY_IOS || UNITY_ANDROID shader_name = xc.ResPath.MAT_UI_IMAGE_GREY_ETC_SHADER; //GreyShaderPathName_ETC; #else shader_name = xc.ResPath.MAT_UI_IMAGE_GREY_SHADER; //GreyShaderPathName; #endif SGameEngine.ResourceLoader.Instance.LoadAssetAsync("Assets/" + shader_name, ShaderFinishLoad); } } else { m_default_mat = null; m_default_shader = null; } }
//************************************ // Method: try load a general asset (any type inherited from UnityEngine.Object) //Notice : this will quickly load an asset if it already in cache, but it may fail //************************************ public bool try_load_asset_immediately(string _asset_path, Type _type, AssetResource _result, bool _lock_asset = true) { if (is_destroyed_) { return(false); } if (_result.get_obj() != null) { Debug.LogError("resused an old assetresoure! you should create a new!"); return(false); } if (!bundleobj_cache_.is_first_resource_loaded()) { return(false); } if (_lock_asset) { if (asset_lock_.is_locked(_asset_path)) { return(false); } } AssetObject found_obj = assetobj_cache_.get_from_cache(_asset_path); if (found_obj != null) { _result.set_obj(found_obj); } else { return(false); } return(true); }
/// <summary> /// 停止播放剧情 /// </summary> /// <param name="timelineInfo"></param> void StopImpl(TimelineInfo timelineInfo) { //GameDebug.LogError("TimelineManager.StopImpl: " + timelineInfo.Id); Actor localPlayer = Game.Instance.GetLocalPlayer(); if (localPlayer != null) { if (Game.Instance.CameraControl != null) { Game.Instance.CameraControl.Target = localPlayer.Trans; Game.Instance.CameraControl.NeedFollowInterpolation = timelineInfo.NeedCameraFollowInterpolationWhenFinished; } else { GameDebug.LogError("Stop timeline error, CameraControl is null!!!"); } } else { // 播放动画的时候有可能还没登录游戏,所以LocalPlayer有可能不存在,这里的报错屏蔽掉 //GameDebug.LogError("Stop timeline error, can not get local player!!!"); } if (Game.Instance.MainCamera != null) { Cinemachine.CinemachineBrain cinemachineBrain = Game.Instance.MainCamera.GetComponent <Cinemachine.CinemachineBrain>(); if (cinemachineBrain != null) { cinemachineBrain.enabled = false; } Game.Instance.MainCamera.transform.rotation = mCameraRotationBeforePlay; Game.Instance.MainCamera.fieldOfView = mCameraFOVBeforePlay; } else { GameDebug.LogError("Stop timeline error, can not get main camera!!!"); } if (timelineInfo.PlayableDirector != null) { timelineInfo.PlayableDirector.time = timelineInfo.PlayableDirector.duration; GameObject.DestroyImmediate(timelineInfo.PlayableDirector.gameObject); } else { GameDebug.LogError("Stop timeline error, PlayableDirector is null!!!"); } if (timelineInfo.RelatedGameObject != null) { GameObject.DestroyImmediate(timelineInfo.RelatedGameObject); } mPlayingTimeline = null; SetAllActorsVisible(true, timelineInfo.ShowLocalPlayer); // 恢复主角的自动战斗 if (InstanceManager.Instance.IsAutoFighting != mIsAutoFightingWhenPlaying) { InstanceManager.Instance.IsAutoFighting = mIsAutoFightingWhenPlaying; } mIsAutoFightingWhenPlaying = false; GameInput.Instance.EnableInput(true, true); // 恢复CullManager的Update CullManager.Instance.IsEnabled = true; // 显示UI if (timelineInfo.ShowUI == false) { xc.ui.ugui.UIManager.Instance.ShowAllWindow(); } // 恢复新手引导 //GuideManager.Instance.Resume(); // 恢复任务寻路 if (mNavigatingTaskIdBeforePlay > 0) { Task task = TaskManager.Instance.GetTask(mNavigatingTaskIdBeforePlay); if (task != null) { TaskHelper.TaskGuide(task); } mNavigatingTaskIdBeforePlay = 0; } // 恢复背景音乐 if (!GlobalSettings.Instance.MusicMute && timelineInfo.PauseMusic) { AudioManager.Instance.PauseMusic(false); } ClientEventMgr.Instance.FireEvent((int)ClientEvent.CE_TIMELINE_FINISH, new CEventBaseArgs(timelineInfo.Id)); if (timelineInfo.FinishCallback != null) { timelineInfo.FinishCallback(); } // 释放预加载的资源 SGameEngine.AssetResource ar = null; if (mPreloadedTimelineReses.TryGetValue(timelineInfo.Id, out ar) == true) { if (ar != null) { ar.destroy(); } mPreloadedTimelineReses.Remove(timelineInfo.Id); } // 如果有待播放的系统开放动画,则重新开放 if (SysConfigManager.Instance.IsWaiting() == true) { if (SceneHelp.Instance.IsInWildInstance()) { TargetPathManager.Instance.StopPlayerAndReset();//有系统开启停止寻路 ClientEventMgr.GetInstance().FireEvent((int)ClientEvent.CE_NEW_WAITING_SYS, new CEventBaseArgs()); } else { ClientEventMgr.GetInstance().PostEvent((int)ClientEvent.CE_NEW_WAITING_SYS, new CEventBaseArgs()); } } // 短时间内播放同一个模型的动画两次,第二个剧情会播放不出来,调用一下ResourceLoader的gc就好了,通过表格配置 if (timelineInfo.NeedGC == true) { ResourceLoader.Instance.gc(); } }
/// <summary> /// <para>加载UnityEngine.Object资源,资源不再使用后要调用AssetResource.Destroy()来销毁</para> /// <para>_asset_path:资源路径,eg: "Assets/Res/DefaultRes.prefab"</para> /// <para>_type:加载资源的类型</para> /// <para>_result:协程结束后返回加载资源的结果</para> /// <para>_lock_asset:为避免其他协程加载资源,是否进行锁定操作</para> /// <para>_scene_asset:是否是场景资源</para> /// <para>_scene_name:场景资源的名字</para> /// </summary> public IEnumerator load_asset(string _asset_path, Type _type, AssetResource _result, bool _lock_asset = true, bool _scene_asset = false, string _scene_name = "") { if (is_destroyed_) { yield break; } bool is_ui_asset = _asset_path.Contains("Assets/Res/UI"); if (Const.Language != LanguageType.SIMPLE_CHINESE) { LocalizeManager.Instance.LocalizePath(ref _asset_path); } #if UNITY_EDITOR // 在编辑器下检查资源是否添加到打包配置中(因为lightmap的bug,.unity3d场景暂时不进行资源检查) if (!CheckAssetCfged(_asset_path)) { Debug.LogError(string.Format("asset {0} is not configured for bundle, load failed!", _asset_path)); yield break; } #endif if (_result.get_obj() != null) { Debug.LogError("resused an old assetresoure! you should create a new!"); yield break; } //1. 等待first res加载完毕,其中包含bundleinfo while (!bundleobj_cache_.is_first_resource_loaded()) { yield return(new WaitForEndOfFrame()); } loading_ = true; // 检查资源对应的分包是否已经下载完毕 int patch_id; if (!xpatch.XPatchManager.Instance.IsAssetDownloaded(_asset_path, out patch_id)) { Debug.Log(string.Format("asset {0} is not download for bundle!", _asset_path)); yield break; } //2. 锁定资源,避免加载同一份asset IEnumerator ielock = null; if (_lock_asset) { if (!asset_lock_.try_lock(_asset_path)) { ielock = asset_lock_.try_lock_croutine(_asset_path); coroutine_locked_assets_.Add(ielock, _asset_path); yield return(StartCoroutine(ielock)); } } //3. 检查Cache中是否已经有对应的bundle,否则需要进行加载 AssetObject found_obj = assetobj_cache_.get_from_cache(_asset_path); if (found_obj != null) { _result.set_obj(found_obj); if (_scene_asset) { //load level sceneLoadAsyncOp = SceneManager.LoadSceneAsync(_scene_name); yield return(sceneLoadAsyncOp); } } else { #if UNITY_EDITOR if (!EnableBundleInEditor) { //editor enviroment yield return(StartCoroutine(load_asset_from_assetdatabase(_asset_path, _type, _result, _lock_asset, _scene_asset, _scene_name))); } else #endif { //bundle enviroment //4.从bundleinfo中获取asset的依赖项 AssetBundleInfoItem bundle_info = bundleobj_cache_.get_asset_bundle_info(_asset_path); if (bundle_info == null) { Debug.LogError("Dynamic bundle not find!Editor path is " + _asset_path); goto EXIT_LOAD_ASSET; } UnityEngine.Object loaded_asset = null; List <BundleObject> all_bundles = new List <BundleObject>(); List <List <string> > sort_depends_list = bundleobj_cache_.get_asset_all_dependence(_asset_path); foreach (List <string> sub_list in sort_depends_list) { // 先判断是否在Cache中 if (bundleobj_cache_.is_all_in_cache(sub_list)) { foreach (string path in sub_list) { load_bundle_from_cache(path, all_bundles); } } else { List <string> fail_list = new List <string>(); yield return(StartCoroutine(try_load_bundle_list_coroutine(sub_list, all_bundles, fail_list, is_ui_asset))); //被其他协程锁定的bundle等待解锁后再进行加载 foreach (string depend_bundle_path in fail_list) { //lock if (!bundle_lock_.try_lock(depend_bundle_path)) { yield return(StartCoroutine(bundle_lock_.try_lock_croutine(depend_bundle_path))); } //load bundle and add ref if (!load_bundle_from_cache(depend_bundle_path, all_bundles)) { yield return(StartCoroutine(load_bundle_from_disk_coroutine(depend_bundle_path, all_bundles, is_ui_asset))); } //unlock bundle_lock_.unlock(depend_bundle_path); } } } //5.锁定asset并进行加载 if (!bundle_lock_.try_lock(_asset_path)) { yield return(StartCoroutine(bundle_lock_.try_lock_croutine(_asset_path))); } //load bundle and add ref if (!load_bundle_from_cache(_asset_path, all_bundles)) { yield return(StartCoroutine(load_bundle_from_disk_coroutine(_asset_path, all_bundles, is_ui_asset))); } //unlock bundle_lock_.unlock(_asset_path); if (all_bundles.Count < 1) { goto EXIT_LOAD_ASSET; } //6.从bundle中加载mainasset // 在调用Bundle.Load()之前,需要将缓存所有的依赖bundle if (!_scene_asset) { BundleObject root = all_bundles[all_bundles.Count - 1]; // 获取在bundle中的资源名字 /*string asset_name = root.get_asset_path_; * int last_path_idx = asset_name.LastIndexOf('/'); * if(last_path_idx != -1) * asset_name = asset_name.Substring(last_path_idx + 1); * last_path_idx = asset_name.LastIndexOf('.'); * if (last_path_idx != -1) * asset_name = asset_name.Substring(0, last_path_idx);*/ //loaded_asset = bundleobj_cache_.load_main_asset(root.get_asset_bundle_, _type, BundleNameDef.MAIN); var loadReq = root.get_asset_bundle_.LoadAssetAsync(BundleNameDef.MAIN, _type); yield return(loadReq); loaded_asset = loadReq.asset; if (loaded_asset == null) { Debug.LogError(string.Format("asset counld not be loaded {0} ,check xls or your project", _asset_path)); // 加载失败后要将依赖的bundle的引用计数减少 foreach (BundleObject bo in all_bundles) { bo.decrease_ref();// 因为load bundle的时候增加了引用计数,所以此处需要减少 } goto EXIT_LOAD_ASSET; } } // 场景资源在缓存bundle之后就可以使用 else { sceneLoadAsyncOp = SceneManager.LoadSceneAsync(_scene_name); yield return(sceneLoadAsyncOp); } //7. 创建assetobject并添加到Cache中 AssetObject ao = _scene_asset ? new SceneAssetObject(_asset_path) : new AssetObject(_asset_path, loaded_asset); foreach (BundleObject bo in all_bundles) { AssetBundleInfoItem bundle_item_depend = bundleobj_cache_.get_asset_bundle_info(bo.get_asset_path_); bool shared = bundle_item_depend.shared; // 当assetbundle不被多个资源引用时,可以立即将assetbundle的文件镜像卸载,并从Cache中清除 // Atlas经过特殊处理,虽然被多个资源引用,但是也会立即卸载 /// FIXME /// 在2017版本中,此时unload assetbundle会报错 /*if(!shared) * { * bo.destroy(false); * bundleobj_cache_.remove_bundle_object_from_cache(bo.get_asset_path_); * } * else*/ { ao.add_depend_bundle(bo); } bo.decrease_ref();//decrease the ref added by load bundle } all_bundles.Clear(); assetobj_cache_.put_to_cache(_asset_path, ao); _result.set_obj(ao); } } //9.unlock asset EXIT_LOAD_ASSET: //unlock if (_lock_asset) { if (ielock != null) { coroutine_locked_assets_.Remove(ielock); } asset_lock_.unlock(_asset_path); } loading_ = false; }
/// <summary> /// <para>加载prefab并进行实例化,实例化后的GameObject会添加到dic_gameobj_asset_中</para> /// <para>调用gc时如果GameObject实例已经销毁,则会自动减少对应AssetObject的引用计数</para> /// <para>创建后返回的GameObject最好不要再进行Clone,因为GameObject被销毁后,Clone的实例资源也可能丢失</para> /// </summary> public IEnumerator load_prefab(string _asset_path, PrefabResource _result, bool _dont_destroy_on_load = false, bool _cache_global_bundle = false, Transform parent = null) { if (Const.Language != LanguageType.SIMPLE_CHINESE) { LocalizeManager.Instance.LocalizePath(ref _asset_path); } if (is_destroyed_) { yield break; } string lower_case = _asset_path.ToLower(); if (!lower_case.EndsWith(CACHE_STR_PREFAB)) { Debug.LogError(string.Format("{0} is not a prefab!", lower_case)); yield break; } //1. lock the asset //do nothing //2. load asset and instantiate prefab AssetResource ar = new AssetResource(); yield return(StartCoroutine(load_asset(_asset_path, type_game_object_, ar))); if (ar.asset_ != null) { /*if(_asset_path.Contains("/Res/UI/") && !_asset_path.Contains("/Res/UI/Atlas/") && _asset_path.EndsWith(".prefab")) * { * yield return StartCoroutine(load_atlas(ar)); * }*/ _result.obj_ = instantiate_prefab_from_asset_object(ar, parent); if (_dont_destroy_on_load) { GameObject.DontDestroyOnLoad(_result.obj_); } //adjust the gameobject postion to not be seen directly (_result.obj_ as GameObject).transform.position = new Vector3(-100, -1000, -100); } //3.已经在instantiate_prefab_from_asset_object进行了实例化,可以释放AssetResource对AssetObject的引用 if (!_cache_global_bundle) { ar.destroy(); } else { if (mGlobalCache.ContainsKey(_asset_path)) { ar.destroy(); } else { mGlobalCache[_asset_path] = true; } } //4.unlock asset //do nothing }
//load asset in editor mode,directly from the assetdatabase #if UNITY_EDITOR private IEnumerator load_asset_from_assetdatabase(string _asset_path, Type _type, AssetResource _result, bool _lock_asset = true, bool _scene_asset = false, string _scene_name = "") { yield return(null);//force wait one frame to simulate the async logic UnityEngine.Object loaded_asset = null; if (_scene_asset) { // Temp Test Quad Tree Scene // if(_scene_name == "X4_zhucheng_001") // { // _scene_name = "daditu_001"; // } //Test End //load level sceneLoadAsyncOp = SceneManager.LoadSceneAsync(_scene_name); yield return(sceneLoadAsyncOp); } else { //loaded_asset = Resources.Load(_asset_path, _type); loaded_asset = EditorResourceLoader.LoadAssetAtPath(_asset_path, _type); if (loaded_asset == null) { Debug.LogError(string.Format("asset counld not be loaded {0},check xls or your project", _asset_path)); yield break; } } //create the assetobject AssetObject ao = _scene_asset ? new SceneAssetObject(_asset_path) : new AssetObject(_asset_path, loaded_asset); assetobj_cache_.put_to_cache(_asset_path, ao); _result.set_obj(ao); }