当前位置:   article > 正文

Unity组件开发--UI管理器_unity ui管理器

unity ui管理器

1.Canvas组件:

注意属性:

(1)渲染模式是:屏幕空间相机

(2)创建一个UICamera节点,管理相机

(3)屏幕画布缩放模式

(4)画布下挂载两个脚本:UIRoot和UIManager

(5)事件系统管理节点必须有:

2.画布下其他节点类型:用于不同界面类型的管理归类window类型

3.先看UIRoot脚本:

  1. using UnityEngine;
  2. /// <summary>
  3. /// 这个脚本用来定位UIROOT,因为GameObject.Find在浏览器上会踩坑
  4. /// </summary>
  5. public class UIRoot : MonoBehaviour {
  6. private void Awake() {
  7. DontDestroyOnLoad(gameObject);
  8. }
  9. void Start () {
  10. }
  11. }

4.所有的UI界面预设体都用一个json文本管理起来:UIPanelType

  1. {
  2. "infoList":
  3. [
  4. {"panelTypeString":"HOME_PANEL",
  5. "path":"HomePanel"},
  6. {"panelTypeString":"WELCOME_PANEL",
  7. "path":"WelcomePanel"},
  8. {"panelTypeString":"MAIN_PANEL",
  9. "path":"MainPanel"}
  10. ]
  11. }

5.上面这个json文件中的path,对应的就是UI预设体的名字:由于我们的UI预制体都是用AB包的方式加载的,就都放在BundleAsset文件夹中

6.C#代码中也有有一个对应UI预设体名字的枚举类:

  1. public enum UIPanelType {
  2. ALERT_PANEL,
  3. CONNECT_PANEL,
  4. HOME_PANEL,
  5. WELCOME_PANEL,
  6. MAIN_PANEL,
  7. }

7.然后所有UI类脚本必须继承的基类:BasePanel

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. [RequireComponent(typeof(CanvasGroup))]
  6. public class BasePanel : MonoBehaviour {
  7. public enum PanelLayer {
  8. Normal,
  9. Hud,
  10. Addition,
  11. Windows,
  12. Wanring,
  13. ModelView,
  14. }
  15. [HideInInspector]
  16. public UIPanelType panelTpe;
  17. public PanelLayer Layer;
  18. protected CanvasGroup canvasGroup;
  19. protected virtual void Awake() {
  20. 子类会继承这个函数,所以这里不应该写任何代码
  21. //name = GetType() + ">>";
  22. //canvasGroup = gameObject.GetComponent<CanvasGroup>();
  23. }
  24. protected new string name;
  25. /// <summary>
  26. /// 开启交互,页面显示
  27. /// </summary>
  28. public virtual void OnEnter() {
  29. //Debug.Log(name + "Enter");
  30. SetPanelActive(true);
  31. SetPanelInteractable(true);
  32. }
  33. /// <summary>
  34. /// 界面暂停,关闭交互
  35. /// </summary>
  36. public virtual void OnPause() {
  37. SetPanelInteractable(false);
  38. }
  39. /// <summary>
  40. /// 界面继续,恢复交互
  41. /// </summary>
  42. public virtual void OnResume() {
  43. SetPanelInteractable(true);
  44. }
  45. /// <summary>
  46. /// 界面不显示,退出这个界面,界面被关闭
  47. /// </summary>
  48. public virtual void OnExit() {
  49. SetPanelActive(false);
  50. SetPanelInteractable(false);
  51. }
  52. /// <summary>
  53. /// 关闭自身
  54. /// </summary>
  55. public void CloseSelf() {
  56. SetPanelActive(false);
  57. UIManager.Instance.CloseWindowMask();
  58. UIManager.Instance.ClosePannel(panelTpe);
  59. }
  60. private void SetPanelActive(bool isActive) {
  61. //isActive ^= this.gameObject.activeSelf;
  62. bool compare = isActive ^ gameObject.activeSelf;
  63. if (compare) {
  64. gameObject.SetActive(isActive);
  65. }
  66. }
  67. private void SetPanelInteractable(bool isInteractable) {
  68. //canvasGroup = canvasGroup == null ? gameObject.GetComponent<CanvasGroup>() : canvasGroup;
  69. //bool compare = isInteractable ^ canvasGroup;
  70. //if (compare)
  71. //{
  72. // canvasGroup.interactable = isInteractable;
  73. //}
  74. //canvasGroup = canvasGroup == null ? gameObject.GetComponent<CanvasGroup>() : canvasGroup;
  75. //if (isInteractable ^ canvasGroup.interactable) canvasGroup.interactable = isInteractable;
  76. }
  77. }

8.UI管理器脚本:UIManager

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEditor;
  6. using UnityEngine;
  7. using UnityEngine.UI;
  8. using static BasePanel;
  9. public class UIManager : MonoBehaviour {
  10. private static UIManager sInstanceUiManager;
  11. private Dictionary<UIPanelType, string> mPanelPathDictionary;//存储所有面板Prefab的路径
  12. private Dictionary<UIPanelType, BasePanel> mPanelPool;//保存所有实例化面板的游戏物体身上的BasePanel组件
  13. private Stack<BasePanel> mPanelStack; //TODO:需要拆分成多个堆栈,否则会有各种奇怪的问题
  14. private Transform mUIRootTransform;
  15. private GameObject windowsMask;
  16. public static UIManager Instance
  17. {
  18. get { return sInstanceUiManager; }
  19. }
  20. [Serializable]
  21. public class UIPanelTypeJson {
  22. public List<UIPanelInformation> infoList;
  23. }
  24. /// <summary>
  25. /// 实例化UIManager
  26. /// </summary>
  27. /// <returns></returns>
  28. void Awake() {
  29. sInstanceUiManager = this;
  30. DontDestroyOnLoad(gameObject);
  31. ParseUIPanelTypeJson();
  32. mUIRootTransform = GameObject.FindAnyObjectByType<UIRoot>().transform;
  33. windowsMask = mUIRootTransform.Find("Windows/Mask").gameObject;
  34. windowsMask.GetComponent<Button>().onClick.AddListener(ClickMask);
  35. }
  36. /// <summary>
  37. /// 从json配置文件解析为相对应的object类
  38. /// </summary>
  39. private void ParseUIPanelTypeJson() {
  40. mPanelPathDictionary = new Dictionary<UIPanelType, string>();
  41. TextAsset textAsset = Resources.Load<TextAsset>("GameRes/UIPrefabs/UIPanelType");
  42. //将json对象转化为UIPanelTypeJson类
  43. UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(textAsset.text);
  44. foreach (UIPanelInformation info in jsonObject.infoList) {
  45. mPanelPathDictionary.Add(info.panelType, info.path);
  46. }
  47. }
  48. public bool TopPanelIs(UIPanelType panelType) {
  49. BasePanel panel;
  50. mPanelPool.TryGetValue(panelType, out panel);
  51. if (!mPanelStack.Contains(panel))
  52. {
  53. return false;
  54. }
  55. else {
  56. int indexPanel = UtilsFunc.GetStackIndex(mPanelStack, panel);
  57. if (indexPanel!=null) return true;
  58. return false;
  59. }
  60. }
  61. public void CloseLastModelViewTypePanel() {
  62. //从栈顶开始查找指定面板
  63. BasePanel panelToRemove = null;
  64. for (int i = mPanelStack.Count - 1; i >= 0; i--)
  65. {
  66. BasePanel panel = mPanelStack.ElementAt(i);
  67. if (panel.Layer == PanelLayer.ModelView)
  68. {
  69. //找到则关闭页面
  70. panelToRemove = panel;
  71. panel.OnExit();
  72. break;
  73. }
  74. }
  75. if (panelToRemove != null)
  76. {
  77. //移除要关闭的面板
  78. mPanelStack.Pop();
  79. //重新压入除要移除的面板外的所有面板
  80. Stack<BasePanel> tempStack = new Stack<BasePanel>();
  81. while (mPanelStack.Count > 0)
  82. {
  83. BasePanel panel = mPanelStack.Pop();
  84. if (panel != panelToRemove)
  85. {
  86. tempStack.Push(panel);
  87. }
  88. }
  89. while (tempStack.Count > 0)
  90. {
  91. BasePanel panel = tempStack.Pop();
  92. mPanelStack.Push(panel);
  93. }
  94. }
  95. }
  96. public bool IsOpenModelView() {
  97. for (int i = mPanelStack.Count - 1; i >= 0; i--)
  98. {
  99. BasePanel panel = mPanelStack.ElementAt(i);
  100. if (panel.Layer == PanelLayer.ModelView)
  101. {
  102. return true;
  103. }
  104. }
  105. return false;
  106. }
  107. /// <summary>
  108. /// 获得一个指定页面
  109. /// </summary>
  110. /// <param name="panelType">指定页面类型</param>
  111. /// <returns>返回该页面的BasePanel</returns>
  112. private void GetPanel(UIPanelType panelType) {
  113. if (mPanelPool == null) {
  114. mPanelPool = new Dictionary<UIPanelType, BasePanel>();
  115. }
  116. BasePanel panel;
  117. //从页面池中尝试找到指定页面的示例
  118. mPanelPool.TryGetValue(panelType, out panel);
  119. if (panel == null) {
  120. if (mPanelPool.ContainsKey(panelType)) {//意味着正在加载,不需要重复调用
  121. return;
  122. }
  123. string path;
  124. mPanelPathDictionary.TryGetValue(panelType, out path);
  125. #if !UNITY_EDITOR
  126. AppConst.UseAssetBundle = true;
  127. #endif
  128. mPanelPool.Add(panelType, null);
  129. if (AppConst.UseAssetBundle) {
  130. var addressPath = "Prefab/UIPrefabs/" + path;
  131. AssetBundleManager.Instance.LoadPrefab(addressPath, (instancePanel) => {
  132. if (instancePanel != null) {
  133. var targetPanel = instancePanel.GetComponent<BasePanel>();
  134. SetPanel(targetPanel, panelType);
  135. }
  136. else {
  137. Debug.LogError($"error {addressPath}");
  138. }
  139. });
  140. }
  141. else {
  142. StartCoroutine(coEnsureWaitTime(panelType,path));
  143. }
  144. }
  145. else {
  146. if (panel.Layer != BasePanel.PanelLayer.Wanring) {
  147. panel.transform.SetAsLastSibling();
  148. if (mPanelStack.Contains(panel) == false) { //不存在才加入
  149. mPanelStack.Push(panel);
  150. }
  151. else { //存在的话将其移动到栈顶
  152. ToStackTop(panel);
  153. }
  154. }
  155. panel.OnEnter(); //OnEnter在 SetAsLastSibling 之后的目的是要置顶其他页面的时候可以生效
  156. }
  157. }
  158. void SetPanel(BasePanel targetPanel, UIPanelType panelType) {
  159. targetPanel.panelTpe = panelType;
  160. AddLayer(targetPanel);
  161. mPanelPool[panelType] = targetPanel;
  162. targetPanel.transform.SetAsLastSibling();
  163. if (targetPanel.Layer != BasePanel.PanelLayer.Wanring) {
  164. mPanelStack.Push(targetPanel);
  165. }
  166. targetPanel.OnEnter();
  167. }
  168. private void ToStackTop(BasePanel panel) {
  169. var tempStack = new Stack<BasePanel>();
  170. var tempPanel = mPanelStack.Pop();
  171. while (tempPanel != panel && mPanelStack.Count > 0) {
  172. tempStack.Push(tempPanel);
  173. tempPanel = mPanelStack.Pop();
  174. }
  175. if (tempPanel == panel) {
  176. mPanelStack.Push(tempPanel);
  177. }
  178. while (tempStack.Count > 0) {
  179. mPanelStack.Push(tempStack.Pop());
  180. }
  181. }
  182. IEnumerator coEnsureWaitTime(UIPanelType panelType, string path) {
  183. yield return new WaitForSeconds(0.1f);
  184. #if UNITY_EDITOR
  185. var editorPath = "Assets/BundleAsset/Prefab/UIPrefabs/" + path + ".prefab";
  186. Debug.Log("load ui :"+editorPath);
  187. var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(editorPath);
  188. GameObject instancePanel = Instantiate(prefab) as GameObject;
  189. if (instancePanel != null) {
  190. var targetPanel = instancePanel.GetComponent<BasePanel>();
  191. SetPanel(targetPanel, panelType);
  192. }
  193. #endif
  194. }
  195. private void ClickMask() {
  196. windowsMask.gameObject.SetActive(false);
  197. var topPanel = mPanelStack.Peek();
  198. topPanel.CloseSelf();
  199. }
  200. public void PreLoadUI(UIPanelType panelType) {
  201. if (mPanelPool == null)
  202. {
  203. mPanelPool = new Dictionary<UIPanelType, BasePanel>();
  204. }
  205. BasePanel panel;
  206. //从页面池中尝试找到指定页面的示例
  207. mPanelPool.TryGetValue(panelType, out panel);
  208. if (panel == null)
  209. {
  210. string path;
  211. mPanelPathDictionary.TryGetValue(panelType, out path);
  212. #if !UNITY_EDITOR
  213. AppConst.UseAssetBundle = true;
  214. #endif
  215. if (AppConst.UseAssetBundle)
  216. {
  217. var addressPath = "Prefab/UIPrefabs/" + path;
  218. AssetBundleManager.Instance.PreLoadBundle(addressPath);
  219. }
  220. }
  221. }
  222. public void OpenWindowMask() {
  223. EventManager.Instance.TriggerEvent(EventName.UIInteraction);
  224. windowsMask.SetActive(true);
  225. windowsMask.transform.SetAsLastSibling();
  226. if (mPanelStack != null) {
  227. var topPanel = mPanelStack.Peek();
  228. topPanel.transform.SetAsLastSibling();
  229. }
  230. }
  231. public void CloseWindowMask() {
  232. EventManager.Instance.TriggerEvent(EventName.ExitUIInteraction);
  233. windowsMask.SetActive(false);
  234. }
  235. /// <summary>
  236. /// 显示指定的面板
  237. /// </summary>
  238. /// <param name="panelType"></param>
  239. public void PushPanel(UIPanelType panelType) {
  240. if (mPanelStack == null)
  241. mPanelStack = new Stack<BasePanel>();
  242. //判断一下栈里面是否有页面
  243. if (mPanelStack.Count > 0) {
  244. var topPanel = mPanelStack.Peek();
  245. topPanel.OnPause();
  246. }
  247. this.CloseLastModelViewTypePanel();
  248. GetPanel(panelType);
  249. }
  250. public void CloseAllPannel() {
  251. for (int i = mPanelStack.Count - 1; i >= 0; i--)
  252. {
  253. BasePanel panel = mPanelStack.ElementAt(i);
  254. panel.OnExit();
  255. mPanelStack.Pop();
  256. }
  257. }
  258. /// <summary>
  259. /// 从栈里面找到指定面板将其关闭
  260. /// </summary>
  261. /// <param name="panelType"></param>
  262. public void ClosePannel(UIPanelType panelType) {
  263. if (mPanelPool.ContainsKey(panelType) == false) {
  264. Debug.LogError($"ClosePannel {panelType} null");
  265. return;
  266. }
  267. if (mPanelStack == null)
  268. return;
  269. //从栈顶开始查找指定面板
  270. BasePanel panelToRemove = null;
  271. for (int i = mPanelStack.Count - 1; i >= 0; i--) {
  272. BasePanel panel = mPanelStack.ElementAt(i);
  273. if (mPanelPool[panelType] == panel) {
  274. //找到则关闭页面
  275. panelToRemove = panel;
  276. panel.OnExit();
  277. break;
  278. }
  279. }
  280. if (panelToRemove != null) {
  281. //重新压入除要移除的面板外的所有面板
  282. Stack<BasePanel> tempStack = new Stack<BasePanel>();
  283. while (mPanelStack.Count > 0) {
  284. BasePanel panel = mPanelStack.Pop();
  285. if (panel != panelToRemove) {
  286. tempStack.Push(panel);
  287. }
  288. }
  289. while (tempStack.Count > 0) {
  290. BasePanel panel = tempStack.Pop();
  291. mPanelStack.Push(panel);
  292. }
  293. }
  294. }
  295. /// <summary>
  296. /// 关闭页面并显示新的页面
  297. /// </summary>
  298. /// <param name="panelType"></param>
  299. /// <param name="isPopCurrentPanel">true时, 关闭当前页面; false时, 关闭所有页面</param>
  300. public void PushPanel(UIPanelType panelType, bool isPopCurrentPanel) {
  301. if (isPopCurrentPanel) {
  302. PopCurrentPanel();
  303. }
  304. else {
  305. PopAllPanel();
  306. }
  307. PushPanel(panelType);
  308. }
  309. /// <summary>
  310. /// 返回上一个页面
  311. /// </summary>
  312. /// <returns></returns>
  313. public bool BackToLastPanel() {
  314. //判断当前栈是否为空??表示是否可以返回
  315. if (mPanelStack == null)
  316. mPanelStack = new Stack<BasePanel>();
  317. if (mPanelStack.Count <= 1) return false;
  318. //关闭栈顶页面的显示
  319. var topPanel1 = mPanelStack.Pop();
  320. topPanel1.OnExit();
  321. //恢复此时栈顶页面的交互
  322. BasePanel topPanel2 = mPanelStack.Peek();
  323. topPanel2.OnResume();
  324. return true;
  325. }
  326. void AddLayer(BasePanel panel) {
  327. Transform dstParent = null;
  328. switch (panel.Layer) {
  329. case BasePanel.PanelLayer.Normal:
  330. dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Normal));
  331. break;
  332. case BasePanel.PanelLayer.Hud:
  333. dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Hud));
  334. break;
  335. case BasePanel.PanelLayer.Addition:
  336. dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Addition));
  337. break;
  338. case BasePanel.PanelLayer.Windows:
  339. dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Windows));
  340. break;
  341. case BasePanel.PanelLayer.Wanring:
  342. dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Wanring));
  343. break;
  344. case BasePanel.PanelLayer.ModelView:
  345. dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.ModelView));
  346. break;
  347. default:
  348. break;
  349. }
  350. panel.transform.SetParent(dstParent,false);
  351. }
  352. /// <summary>
  353. /// 隐藏当前面板
  354. /// </summary>
  355. private void PopCurrentPanel() {
  356. if (mPanelStack == null)
  357. mPanelStack = new Stack<BasePanel>();
  358. if (mPanelStack.Count <= 0) return;
  359. //关闭栈顶页面的显示
  360. BasePanel topPanel = mPanelStack.Pop();
  361. topPanel.OnExit();
  362. }
  363. /// <summary>
  364. /// 隐藏所有面板
  365. /// </summary>
  366. public void PopAllPanel() {
  367. if (mPanelStack == null)
  368. mPanelStack = new Stack<BasePanel>();
  369. if (mPanelStack.Count <= 0) return;
  370. //关闭栈里面所有页面的显示
  371. while (mPanelStack.Count > 0) {
  372. BasePanel topPanel = mPanelStack.Pop();
  373. topPanel.OnExit();
  374. }
  375. }
  376. /// <summary>
  377. /// 切换场景前,调用该方法来清空当前场景的数据
  378. /// </summary>
  379. public void RefreshDataOnSwitchScene() {
  380. mPanelPathDictionary.Clear();
  381. mPanelStack.Clear();
  382. }
  383. }

9.AB包加载管理器:AssetBundleManager

  1. using Cysharp.Threading.Tasks;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Net.WebSockets;
  6. using System.Threading.Tasks;
  7. using UnityEngine;
  8. using UnityEngine.Networking;
  9. using UnityEngine.SceneManagement;
  10. public class AssetBundleManager : MonoBehaviour {
  11. private static AssetBundleManager instance;
  12. private Dictionary<string, List<Action<GameObject>>> m_loadingActions = new Dictionary<string, List<Action<GameObject>>>();
  13. public static AssetBundleManager Instance {
  14. get {
  15. if (instance == null) {
  16. instance = new GameObject("AssetBundleManager").AddComponent<AssetBundleManager>();
  17. }
  18. return instance;
  19. }
  20. }
  21. private Dictionary<string, AssetBundle> loadedAssetBundles = new Dictionary<string, AssetBundle>();
  22. //public AssetBundle LoadAssetBundle(string bundleName, string sceneName = "") {
  23. // if (loadedAssetBundles.ContainsKey(bundleName)) {
  24. // return null;
  25. // }
  26. // string path = Application.streamingAssetsPath + "/" + bundleName;
  27. // AssetBundle bundle = AssetBundle.LoadFromFile(path);
  28. // if (bundle == null) {
  29. // Debug.LogError($"Failed to load asset bundle: {bundleName}");
  30. // return null;
  31. // }
  32. // loadedAssetBundles.Add(bundleName, bundle);
  33. // if (!string.IsNullOrEmpty(sceneName)) {
  34. // SceneManager.LoadScene(sceneName, LoadSceneMode.Additive);
  35. // }
  36. // return bundle;
  37. //}
  38. public void UnloadAssetBundle(string bundleName, string sceneName = "") {
  39. if (!loadedAssetBundles.ContainsKey(bundleName)) {
  40. return;
  41. }
  42. AssetBundle bundle = loadedAssetBundles[bundleName];
  43. bundle.Unload(true);
  44. loadedAssetBundles.Remove(bundleName);
  45. if (!string.IsNullOrEmpty(sceneName)) {
  46. SceneManager.UnloadSceneAsync(sceneName);
  47. }
  48. }
  49. public bool IsAssetBundleLoaded(string bundleName) {
  50. return loadedAssetBundles.ContainsKey(bundleName);
  51. }
  52. /// <summary>
  53. /// 示例 Prefab/Com/NpcHello
  54. /// </summary>
  55. /// <param name="prefabPath"></param>
  56. /// <param name="callback"></param>
  57. public void LoadPrefab(string prefabPath,System.Action<GameObject> callback) {
  58. if (m_loadingActions.TryGetValue(prefabPath,out var list)) {
  59. list.Add(callback);
  60. return; //这里返回不需要再开启协程
  61. }
  62. else {
  63. m_loadingActions.Add(prefabPath, new List<Action<GameObject>>());
  64. m_loadingActions[prefabPath].Add(callback);
  65. }
  66. StartCoroutine(LoadPrefabCoroutine(prefabPath));
  67. }
  68. enum Platefrom
  69. {
  70. PC,
  71. Mobile
  72. }
  73. string GetPrefabName(string prefabPath, Platefrom platefrom)
  74. {
  75. string desPlatform = "";
  76. if (platefrom == Platefrom.Mobile)
  77. {
  78. desPlatform = prefabPath + "_Mobile";
  79. }
  80. else
  81. {
  82. desPlatform = prefabPath;
  83. }
  84. var prefabName = UtilsFunc.GetFileNameWithoutExtension(desPlatform) + ".prefab";
  85. return prefabName;
  86. }
  87. private IEnumerator LoadPrefabCoroutine(string prefabPath) {
  88. var desPlatform = "";
  89. Debug.Log("UI路径LoadPrefabCoroutine......" + prefabPath);
  90. if (!PlayerData.Instance.isRunningPC)
  91. {
  92. desPlatform = prefabPath + "_Mobile";
  93. }
  94. else
  95. {
  96. desPlatform = prefabPath;
  97. }
  98. desPlatform = $"{Host.AssetBundleIP}/{desPlatform.ToLower()}.bundle";
  99. string prefabName = "";
  100. string bundlePath = $"{prefabPath.ToLower()}.bundle";
  101. string fullBundlepath = $"{Host.AssetBundleIP}/{bundlePath.ToLower()}";
  102. AssetBundle bundle = null;
  103. if (loadedAssetBundles.ContainsKey(prefabPath)) {
  104. yield return new WaitForEndOfFrame();
  105. bundle = loadedAssetBundles[prefabPath];
  106. if (bundle.Contains(GetPrefabName(prefabPath,Platefrom.Mobile)))
  107. {
  108. prefabName = GetPrefabName(prefabPath, Platefrom.Mobile);
  109. }
  110. else
  111. {
  112. prefabName = GetPrefabName(prefabPath, Platefrom.PC);
  113. }
  114. }
  115. else {
  116. #if UNITY_EDITOR
  117. if (AppConst.useShowBundlePath) { //打需要演示的包时候需要先读取本地的streamAsset,如果存在侧不执行
  118. var showBundlePath = Application.streamingAssetsPath + $"/webgl/{bundlePath.ToLower()}";
  119. Debug.Log("showBundlePath:"+ showBundlePath);
  120. UnityWebRequest showRequest = UnityWebRequestAssetBundle.GetAssetBundle(showBundlePath);
  121. yield return showRequest.SendWebRequest();
  122. if (showRequest.result == UnityWebRequest.Result.Success) {
  123. Debug.Log($"load bundle ok: {showBundlePath}");
  124. bundle = DownloadHandlerAssetBundle.GetContent(showRequest);
  125. }
  126. else {
  127. UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
  128. yield return request.SendWebRequest();
  129. if (request.result != UnityWebRequest.Result.Success) {
  130. Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
  131. yield break;
  132. }
  133. Debug.Log($"load bundle ok: {fullBundlepath}");
  134. bundle = DownloadHandlerAssetBundle.GetContent(request);
  135. }
  136. }else {
  137. UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
  138. yield return request.SendWebRequest();
  139. if (request.result != UnityWebRequest.Result.Success) {
  140. Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");
  141. request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
  142. yield return request.SendWebRequest();
  143. if (request.result != UnityWebRequest.Result.Success) {
  144. Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
  145. yield break;
  146. }
  147. Debug.Log($"load bundle ok: {fullBundlepath}");
  148. prefabName = GetPrefabName(prefabPath,Platefrom.PC);
  149. bundle = DownloadHandlerAssetBundle.GetContent(request);
  150. }else{
  151. Debug.Log($"load bundle ok: {desPlatform}");
  152. prefabName = GetPrefabName(prefabPath, PlayerData.Instance.isRunningPC ? Platefrom.PC : Platefrom.Mobile);
  153. bundle = DownloadHandlerAssetBundle.GetContent(request);
  154. }
  155. }
  156. #else
  157. UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
  158. yield return request.SendWebRequest();
  159. if (request.result != UnityWebRequest.Result.Success)
  160. {
  161. Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");
  162. request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
  163. yield return request.SendWebRequest();
  164. if (request.result != UnityWebRequest.Result.Success)
  165. {
  166. Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
  167. yield break;
  168. }
  169. Debug.Log($"load bundle ok: {fullBundlepath}");
  170. bundle = DownloadHandlerAssetBundle.GetContent(request);
  171. prefabName = GetPrefabName(prefabPath,Platefrom.PC);
  172. }
  173. else {
  174. Debug.Log($"load bundle ok: {desPlatform}");
  175. prefabName = GetPrefabName(prefabPath, PlayerData.Instance.isRunningPC ? Platefrom.PC : Platefrom.Mobile);
  176. bundle = DownloadHandlerAssetBundle.GetContent(request);
  177. }
  178. #endif
  179. loadedAssetBundles.Add(prefabPath, bundle);
  180. }
  181. if (bundle == null) {
  182. Debug.LogError($"Failed to get asset bundle content at path: {fullBundlepath}");
  183. doCallBack(prefabPath);
  184. yield break;
  185. }
  186. else {
  187. ResetBundleMaterials(bundle);
  188. }
  189. Debug.Log($"load bundle ok: {fullBundlepath}");
  190. AssetBundleRequest prefabRequest = bundle.LoadAssetAsync<GameObject>(prefabName);
  191. yield return prefabRequest;
  192. if (prefabRequest.asset == null) {
  193. Debug.LogError($"Failed to load prefab {prefabName} from asset bundle at path: {desPlatform}");
  194. doCallBack(prefabPath);
  195. yield break;
  196. }
  197. doCallBack(prefabPath, prefabRequest.asset);
  198. //bundle.UnloadAsync(true);
  199. }
  200. public void PreLoadBundle(string prefabPath) {
  201. StartCoroutine(PreLoadBundleCoroutine(prefabPath));
  202. }
  203. private IEnumerator PreLoadBundleCoroutine(string prefabPath) {
  204. var desPlatform = "";
  205. Debug.Log("UI路径PreLoadBundleCoroutine......" + prefabPath);
  206. if (!PlayerData.Instance.isRunningPC)
  207. {
  208. desPlatform = prefabPath + "_Mobile";
  209. }
  210. else
  211. {
  212. desPlatform = prefabPath;
  213. }
  214. desPlatform = $"{Host.AssetBundleIP}/{desPlatform.ToLower()}.bundle";
  215. string bundlePath = $"{prefabPath.ToLower()}.bundle";
  216. string prefabName = "";
  217. string fullBundlepath = $"{Host.AssetBundleIP}/{bundlePath.ToLower()}";
  218. AssetBundle bundle = null;
  219. if (loadedAssetBundles.ContainsKey(prefabPath)) {
  220. yield return null;
  221. bundle = loadedAssetBundles[prefabPath];
  222. }
  223. else {
  224. #if !UNITY_EDITOR
  225. if (AppConst.useShowBundlePath) { //打需要演示的包时候需要先读取本地的streamAsset,如果存在侧不执行
  226. var showBundlePath = Application.streamingAssetsPath + $"/webgl/{bundlePath.ToLower()}";
  227. Debug.Log("showBundlePath:"+ showBundlePath);
  228. UnityWebRequest showRequest = UnityWebRequestAssetBundle.GetAssetBundle(showBundlePath);
  229. yield return showRequest.SendWebRequest();
  230. if (showRequest.result == UnityWebRequest.Result.Success) {
  231. Debug.Log($"load bundle ok: {showBundlePath}");
  232. bundle = DownloadHandlerAssetBundle.GetContent(showRequest);
  233. }
  234. else {
  235. UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
  236. yield return request.SendWebRequest();
  237. if (request.result != UnityWebRequest.Result.Success) {
  238. Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
  239. yield break;
  240. }
  241. Debug.Log($"load bundle ok: {fullBundlepath}");
  242. bundle = DownloadHandlerAssetBundle.GetContent(request);
  243. }
  244. }else {
  245. UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
  246. yield return request.SendWebRequest();
  247. if (request.result != UnityWebRequest.Result.Success) {
  248. Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");
  249. request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
  250. yield return request.SendWebRequest();
  251. if (request.result != UnityWebRequest.Result.Success) {
  252. Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
  253. yield break;
  254. }
  255. Debug.Log($"load bundle ok: {fullBundlepath}");
  256. prefabName = UtilsFunc.GetFileNameWithoutExtension(fullBundlepath) + ".prefab";
  257. bundle = DownloadHandlerAssetBundle.GetContent(request);
  258. }else{
  259. Debug.Log($"load bundle ok: {desPlatform}");
  260. prefabName = UtilsFunc.GetFileNameWithoutExtension(desPlatform) + ".prefab";
  261. bundle = DownloadHandlerAssetBundle.GetContent(request);
  262. }
  263. }
  264. #else
  265. UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
  266. yield return request.SendWebRequest();
  267. if (request.result != UnityWebRequest.Result.Success)
  268. {
  269. Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");
  270. request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
  271. yield return request.SendWebRequest();
  272. if (request.result != UnityWebRequest.Result.Success)
  273. {
  274. Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
  275. yield break;
  276. }
  277. Debug.Log($"load bundle ok: {fullBundlepath}");
  278. prefabName = UtilsFunc.GetFileNameWithoutExtension(fullBundlepath) + ".prefab";
  279. bundle = DownloadHandlerAssetBundle.GetContent(request);
  280. }
  281. else {
  282. Debug.Log($"load bundle ok: {desPlatform}");
  283. prefabName = UtilsFunc.GetFileNameWithoutExtension(desPlatform) + ".prefab";
  284. bundle = DownloadHandlerAssetBundle.GetContent(request);
  285. }
  286. #endif
  287. }
  288. if (bundle == null) {
  289. Debug.LogError($"Failed to get asset bundle content at path: {fullBundlepath}");
  290. yield break;
  291. }
  292. loadedAssetBundles.Add(prefabPath, bundle);
  293. }
  294. void doCallBack(string prefabPath, UnityEngine.Object asset = null) {
  295. if (asset == null) {
  296. m_loadingActions.Remove(prefabPath);
  297. return;
  298. }
  299. m_loadingActions.TryGetValue(prefabPath, out var list);
  300. if (list != null) {
  301. foreach (var action in list) {
  302. GameObject prefab = Instantiate(asset) as GameObject;
  303. action(prefab);
  304. }
  305. m_loadingActions.Remove(prefabPath);
  306. }
  307. else {
  308. Debug.LogError($"doCallBack {prefabPath}");
  309. }
  310. }
  311. public async Task<UnityWebRequest> LoadSceneSync(string sceneName) {
  312. string fullBundlepath = $"{Host.AssetBundleIP}/scenes/{sceneName.ToLower()}.bundle";
  313. UnityWebRequest www = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
  314. var asyncOp = await www.SendWebRequest();
  315. if (asyncOp.result != UnityWebRequest.Result.Success) {
  316. Debug.LogError(www.error);
  317. }
  318. else {
  319. Debug.Log("LoadSceneSync");
  320. DownloadHandlerAssetBundle.GetContent(www);
  321. await SceneManager.LoadSceneAsync(sceneName);
  322. ResetSceneAllMaterials();
  323. }
  324. return asyncOp;
  325. }
  326. private void ResetSceneAllMaterials() {
  327. #if UNITY_EDITOR
  328. var scene = SceneManager.GetActiveScene();
  329. GameObject[] roots = scene.GetRootGameObjects();
  330. foreach (GameObject root in roots) {
  331. var renderers = root.GetComponentsInChildren<Renderer>();
  332. foreach (var render in renderers) {
  333. ResetMaterials(render.materials);
  334. }
  335. }
  336. if (RenderSettings.skybox != null)
  337. RenderSettings.skybox.shader = Shader.Find(RenderSettings.skybox.shader.name);
  338. #endif
  339. }
  340. private void ResetMaterials(Material[] materials) {
  341. foreach (Material m in materials) {
  342. var shaderName = m.shader.name;
  343. if (shaderName == "Hidden/InternalErrorShader")
  344. continue;
  345. var newShader = Shader.Find(shaderName);
  346. if (newShader != null) {
  347. m.shader = newShader;
  348. }
  349. else {
  350. Debug.LogWarning("unable to refresh shader: " + shaderName + " in material " + m.name);
  351. }
  352. }
  353. }
  354. private void ResetBundleMaterials(AssetBundle bundle) {
  355. #if UNITY_EDITOR
  356. var materials = bundle.LoadAllAssets<Material>();
  357. ResetMaterials(materials);
  358. #endif
  359. }
  360. void OnDestroy() {
  361. foreach (var bundle in loadedAssetBundles.Values) {
  362. bundle.Unload(true);
  363. }
  364. loadedAssetBundles.Clear();
  365. }
  366. }
  1. public static class Host
  2. {
  3. /// <summary>
  4. /// 如果StreamAsset CONFIG 里面有配置AssetBundleIP,则使用那边的
  5. /// </summary>
  6. public static string AssetBundleIP = Application.dataPath.Replace("Assets", "") + "ABundles/webgl";
  7. public static string gameServer = "";
  8. public static string ApiHost = "";
  9. public static string remote = "";
  10. }

10.新建一个UI预设体:

这个界面的业务脚本:WarningPanel

  1. using System;
  2. using System.Collections;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. public class WarningPanel : BasePanel
  6. {
  7. static string showText;
  8. public Text text;
  9. public GameObject confirmBtn;
  10. public GameObject closeBtn;
  11. private static Action confirmCallBack;
  12. private static Action closeCallBack;
  13. public static void Show(string showText,Action confirmBack,Action closeBack)
  14. {
  15. WarningPanel.showText = showText;
  16. WarningPanel.confirmCallBack = confirmBack;
  17. WarningPanel.closeCallBack = closeBack;
  18. UIManager.Instance.PushPanel(UIPanelType.WARNING_PANEL);
  19. }
  20. public override void OnEnter()
  21. {
  22. base.OnEnter();
  23. text.text = WarningPanel.showText;
  24. confirmBtn.GetComponent<Button>().onClick.AddListener(onClickConfirm);
  25. if(closeBtn!=null) closeBtn.GetComponent<Button>().onClick.AddListener(onClickClose);
  26. }
  27. private void onClickClose()
  28. {
  29. if (WarningPanel.closeCallBack != null) {
  30. WarningPanel.closeCallBack();
  31. }
  32. }
  33. IEnumerator WaitHide()
  34. {
  35. yield return new WaitForSeconds(2f);
  36. gameObject.SetActive(false);
  37. }
  38. private void onClickConfirm()
  39. {
  40. if (WarningPanel.confirmCallBack != null)
  41. {
  42. WarningPanel.confirmCallBack();
  43. //StopAllCoroutines();
  44. //StartCoroutine(WaitHide());
  45. }
  46. gameObject.SetActive(false);
  47. }
  48. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/761524
推荐阅读
相关标签
  

闽ICP备14008679号