using UnityEngine; using System.IO; using System.Collections.Generic; using System.Xml; public class loadLittleGamesPrefab : MonoBehaviour { [Header("Scroll Views")] public GameObject officialDocs_scrollView_content; public GameObject officialGames_scrollView_content; public GameObject thirdPartyGames_scrollView_content; [Header("Prefab")] public GameObject littleGames_card_Prefab; [Header("H5 Root Path (optional, leave empty to use WebViewLauncher settings)")] public string h5RootPath; void Start() { LoadAllLittleGames(); } /// /// 在 WebViewLauncher 的 h5 目录下扫描 three categories 的所有子文件夹(递归一层), /// 找到含有 index.html 的目录(例如: ...\h5LG\_thirdPartyGames\kjb\index.html), /// 读取同目录下的 info.xml(如果存在),并把 prefab 实例化到对应的 content 中。 /// /// info.xml 示例格式(放在同目录下,编码 UTF-8): /// /// /// 示例游戏名 /// 作者名 /// 这里是描述文本 /// True /// 来源信息 /// 2025-12-23 /// /// /// 请保证节点名如上所示以便能被正确读取。 /// public void LoadAllLittleGames() { string root = GetH5RootPath(); if (string.IsNullOrEmpty(root) || !Directory.Exists(root)) { Debug.LogWarning("H5 root path not found: " + root); return; } // 目标一级子目录名称(与 WebViewLauncher 中保持一致) string[] categories = { "_officialDocs", "_officialGames", "_thirdPartyGames" }; foreach (string cat in categories) { string catPath = Path.Combine(root, cat); if (!Directory.Exists(catPath)) continue; // 遍历 catPath 下的第一层子目录,检查是否含有 index.html string[] subdirs = Directory.GetDirectories(catPath); foreach (string subdir in subdirs) { string indexPath = Path.Combine(subdir, "index.html"); if (!File.Exists(indexPath)) { // 也可能 index.html 在更深一层,但按照约定通常是 subdir/index.html continue; } // 读取 info.xml(可选) string infoXmlPath = Path.Combine(subdir, "info.xml"); var meta = ReadInfoXml(infoXmlPath); // 根据分类选择目标 content GameObject targetContent = GetContentByCategory(cat); if (targetContent == null || littleGames_card_Prefab == null) { Debug.LogWarning("Missing prefab or content for category: " + cat); continue; } // 实例化 prefab GameObject go = Instantiate(littleGames_card_Prefab, targetContent.transform); // 设置数据(indexPath 使用本地文件绝对路径) string absIndexPath = indexPath; // 使用绝对路径,WebViewLauncher.OpenUrl 会添加 file:// var prefabComp = go.GetComponent(); if (prefabComp != null) { // 若来自官方分类,覆盖 isOfficial 与 source 字段为固定值 string finalIsOfficial = meta.GetValueOrDefault("isOfficial"); string finalSource = meta.GetValueOrDefault("source"); if (cat == "_officialDocs" || cat == "_officialGames") { finalIsOfficial = "官方"; finalSource = "小游戏DLC"; } else { // 非官方分类统一标记为第三方来源 finalIsOfficial = "第三方来源"; // 若 info.xml 没有 source,则可以保留原值或设置默认,这里若无则为空 if (string.IsNullOrEmpty(finalSource)) finalSource = ""; } // 格式化日期为 yyyy\nmm\ndd 的形式 string rawDate = meta.GetValueOrDefault("yyyy_mm_dd"); string formattedDate = FormatDateWithNewlines(rawDate); prefabComp.SetData(absIndexPath, meta.GetValueOrDefault("card_name"), meta.GetValueOrDefault("authorName"), meta.GetValueOrDefault("description"), finalIsOfficial, finalSource, formattedDate ); } } } } string GetH5RootPath() { if (!string.IsNullOrEmpty(h5RootPath) && Directory.Exists(h5RootPath)) return h5RootPath; // 从 WebViewLauncher 获取编辑器路径 var w = GameObject.FindObjectOfType(); if (w != null) { #if UNITY_EDITOR return w.h5EditorPath; #else return Path.Combine(Application.streamingAssetsPath, "h5LG"); #endif } // 作为回退,使用 StreamingAssets/h5LG return Path.Combine(Application.streamingAssetsPath, "h5LG"); } GameObject GetContentByCategory(string categoryName) { switch (categoryName) { case "_officialDocs": return officialDocs_scrollView_content; case "_officialGames": return officialGames_scrollView_content; case "_thirdPartyGames": return thirdPartyGames_scrollView_content; default: return null; } } Dictionary ReadInfoXml(string xmlPath) { var dict = new Dictionary(); if (string.IsNullOrEmpty(xmlPath) || !File.Exists(xmlPath)) return dict; try { var doc = new XmlDocument(); doc.Load(xmlPath); var root = doc.DocumentElement; if (root == null) return dict; // 读取预定义字段 string[] keys = { "card_name", "authorName", "description", "isOfficial", "source", "yyyy_mm_dd" }; foreach (var k in keys) { var node = root.SelectSingleNode(k); if (node != null) dict[k] = node.InnerText; } } catch (System.Exception e) { Debug.LogWarning("Failed to read info.xml: " + xmlPath + " error: " + e.Message); } return dict; } // 将日期文本尝试解析成 yyyy\nmm\ndd 格式,若解析失败则做简单替换(支持 2025-12-23, 2025/12/23, 2025_12_23, 20251223 等) string FormatDateWithNewlines(string raw) { if (string.IsNullOrEmpty(raw)) return ""; // 尝试按常见分隔符拆分 char[] seps = new char[] { '-', '/', '_', ' ' }; var parts = raw.Split(seps, System.StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 3) { return parts[0] + "\n" + parts[1] + "\n" + parts[2]; } // 尝试连续数字 8 位 var digits = System.Text.RegularExpressions.Regex.Replace(raw, "\\D", ""); if (digits.Length == 8) { string y = digits.Substring(0, 4); string m = digits.Substring(4, 2); string d = digits.Substring(6, 2); return y + "\n" + m + "\n" + d; } // 回退:尝试用第一个 4 位作为年,接下来的两位为月,之后为日 if (digits.Length >= 6) { string y = digits.Substring(0, 4); string m = digits.Length >= 6 ? digits.Substring(4, 2) : ""; string d = digits.Length >= 8 ? digits.Substring(6, 2) : ""; return y + "\n" + m + "\n" + d; } // 最后回退直接把原文本按字符换行(有限长度) return raw.Replace("-", "\n").Replace("/", "\n").Replace("_", "\n"); } // Update is called once per frame void Update() { } }