using cfg.VihecleCultivateCfg; using Cysharp.Threading.Tasks; using Framework; using Gameplay.Character.Utils; using Gameplay.Level; using Newtonsoft.Json; using NLDPB; using PhxhSDK; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using cfg.CharacterCfg; using Gameplay.Unit; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using Constants = Framework.Constants; using cfg.ActorCfg; using UnityEngine.SceneManagement; using Random = UnityEngine.Random; using cfg.ErrorCfg; using cfg.FightCfg; using cfg.LevelCfg; using PhxhSDK.Res; using Gameplay.Performance; using Gameplay.Utils; using Gameplay.Common; using cfg.SkillCfg; using cfg.StringCfg; using Gameplay.Vehicle.Impl; using cfg.LegionBattleCfg; using System.Globalization; #if UNITY_EDITOR using UnityEditor; #endif namespace Gameplay { public partial class CommonUtils { private static RenderTexture screenTexture; private static readonly int MainTex = Shader.PropertyToID("_MainTex"); private static readonly int BlurSize = Shader.PropertyToID("_BlurSize"); private static readonly int ForceGray = Shader.PropertyToID("_ForceGray"); private const string ICON_WEATHER_PREFIX = "Icon_Weather_"; private const string ICON_ENVIRONMENT_PREFIX = "Icon_Environment_"; private const string ICON_DAYNIGHT_PREFIX = "Icon_Daynight_"; private const string SCREEN_SNAPSHOT = "ScreenSnapshot"; public static Texture2D GetScreenTexture2D() { Texture2D texture2D = new(screenTexture.width, screenTexture.height); RenderTexture.active = screenTexture; texture2D.ReadPixels(new Rect(0f, 0f, screenTexture.width, screenTexture.height), 0, 0); texture2D.Apply(); RenderTexture.active = null; return texture2D; } public static void DestoryGameObjectImmediate(ref GameObject obj) { if (null != obj) { GameObject.DestroyImmediate(obj); obj = null; } } public static string GetInternaitionalStr(int strId, string str) { return str; } public static GameObject GetGameObject(GameObject gameObject, string path) { Transform tra = gameObject.transform.Find(path); return null != tra ? tra.gameObject : null; } public static T GetComponent(GameObject gameObject, string path = null) where T : Component { T result = null; if (null == gameObject) { DebugUtil.LogWarning("ParentObjectisNUll: {0}", path); } if (null != path) result = gameObject.transform.Find(path).gameObject.GetComponent(); else result = gameObject.GetComponent(); if (result == null) { DebugUtil.Log(path); } return result; } //获取对象子节点中最上层的那个组件 public static T GetChildComponent(GameObject go) where T : Component { T result = null; if (!go) { DebugUtil.LogWarning("ParentObjectisNUll: {0}", go.name); } var trans = go.transform; for (int i = 0; i < trans.childCount; i++) { var child = trans.GetChild(i); var cmp = child.GetComponent(); if (cmp) { result = cmp; break; } //递归搜索子节点的子节点,返回最上层那个 result = GetChildComponent(child.gameObject); if (result) { break; } } return result; } public static void DestoryAllChildGameObject(GameObject parent) { if (parent != null) { int count = parent.transform.childCount; List childs = new List(); for (int i = 0; i < count; ++i) { childs.Add(parent.transform.GetChild(i)); } for (int i = 0; i < count; ++i) { GameObject.DestroyImmediate(childs[i].gameObject); } } } //??????????? public static string GetWholeHeadPath(string name) { return TableManager.Instance.Tables.GlobalConfig.HeadPicFrontPath + name + ".png"; } /// /// 默认头像路径(建议使用GetCharacterPicPath方法) /// /// /// public static string GetDefaultHeadPathByUid(uint uid) { DebugUtil.Log("获取默认头像路径!如需按选中皮肤显示头像,点击这里查看建议更新方法"); //如需更新代码可以参考这段代码 //var characterInfo = CharacterDataInfoManager.Instance.GetCharacterInfo(uid); //var spritePath = CommonUtils.GetCharacterPicPath((int)uid, CommonUtils.ECharacterPicPathType.HeadPic, (int)characterInfo.SkinID); var cfg = TableManager.Instance.Tables.CharacterAttri.GetOrDefault((int)uid); if (cfg == null) { DebugUtil.LogError("--- 无法获取UID对应的配置 ---"); return ""; } var skinIdx = GLConfig.Inst.data.DEFAULTSKINID; var dataSkin = TableManager.Instance.Tables.SkinCfg.Get(skinIdx, cfg.RoleID); return GetWholeHeadPath(dataSkin.PIcHeadPath); } public static string GetDefaultVehicleHeadPath(uint uid) { var cfg = TableManager.Instance.Tables.VehicleConfig.GetOrDefault((int)uid); if (cfg == null) { DebugUtil.LogError("--- 无法获取UID对应的配置 ---"); return ""; } return "Assets/Art_Out/UI/Texture/Icon/Vehicle/NewHeadPic/" + cfg.UIHeadPath; } public static string GetCharacterName(int RoleId) { var str = "character_name" + RoleId; return GetLocalizeText(str); } public static Army GetArmyByCfg(DataCharacterAttri cfg) { var FactionDetail = cfg.FacDetail; var facCfg = TableManager.Instance.Tables.FactionAttri.GetOrDefault(FactionDetail); if (facCfg == null) { DebugUtil.LogError("--- 无法获取阵营对应的配置 ---"); return default; } return facCfg.Amy; } public static Efaction GetEfactionByCfg(DataCharacterAttri cfg) { var FactionDetail = cfg.FacDetail; var facCfg = TableManager.Instance.Tables.FactionAttri.GetOrDefault(FactionDetail); if (facCfg == null) { DebugUtil.LogError("--- 无法获取阵营对应的配置 ---"); return default; } return facCfg.FactionEnum; } public static Ejob GetProfessionByUid(uint uid) { var cfg = TableManager.Instance.Tables.CharacterAttri.GetOrDefault((int)uid); if (cfg == null) { DebugUtil.LogError("--- 无法获取UID对应的配置 ---"); return default; } return cfg.Job; } //???????? public static string GetWholeLiHuiPath(string name) { return Constants.UI_POSTER_DEFAULT_PATH + name + ".png"; } /// /// 获取军团战关卡数据 /// /// public static string GetLegionBattleLevelData(string dataPath) { return string.Format(Constants.LEGION_BATTLE_LEVEL_DATA_PATH, dataPath); } public static string GetVehicleHeadPath(string name) { return name + ".png"; } public enum ECharacterPicPathType { /// /// 养成主界面用,大半身图 /// Cultivate, /// /// 好感度界面用,全身立绘 /// Favorable, /// /// 技能升级界面用,全身不同尺寸立绘 /// LevelUp, /// /// 选择角色界面用,半身 /// SelectCharacter, /// /// 立绘查看界面用,全身 /// Poster, /// /// 看板娘立绘,该立绘图片仅人物无背景 /// AssistantPoster, /// /// 角色头像 /// HeadPic, } public static string GetCharacterPicPath(int id, ECharacterPicPathType eCharacterPicPathType, int skinID = 1, bool isCommanderHead = false) { cfg.CharacterCfg.SkinCfg postCfg = TableManager.Instance.Tables.SkinCfg; if (postCfg.Get(skinID, id) == null) { DebugUtil.LogError("该id的posterCfg尚未配置", id); return @"Assets/Art_Out/UI/Texture/UI_Pic_Main/UI_Poster/Cutivate/Poster_Cul_001.png"; } string name; string[] split; switch (eCharacterPicPathType) { case ECharacterPicPathType.Cultivate: name = postCfg.Get(1, id).Cultivate; split = name.Split('_'); if (split[1].Equals("Special")) { return @"Assets/Art_Out/UI/Texture/UI_Pic_Main/UI_Poster/Special/" + postCfg.Get(skinID, id).Cultivate + ".png"; } else return Constants.UI_POSTER_DEFAULT_PATH + postCfg.Get(1, id).Cultivate + ".png"; case ECharacterPicPathType.Favorable: name = postCfg.Get(1, id).Favorable; split = name.Split('_'); if (split[1].Equals("Special")) { return @"Assets/Art_Out/UI/Texture/UI_Pic_Main/UI_Poster/Special/" + postCfg.Get(skinID, id).Favorable + ".png"; } else return Constants.UI_POSTER_DEFAULT_PATH + postCfg.Get(1, id).Favorable + ".png"; case ECharacterPicPathType.LevelUp: name = postCfg.Get(1, id).LevelUp; split = name.Split('_'); if (split[1].Equals("Lu")) { DebugUtil.Log("该角色使用旧版立绘资源配置:" + id); return @"Assets/Art_Out/UI/Texture/UI_Pic_Main/UI_Poster/LevelUp/" + postCfg.Get(skinID, id).LevelUp + ".png"; } else return @"Assets/Art_Out/UI/Texture/UI_Pic_Main/UI_Poster/Special/" + postCfg.Get(skinID, id).LevelUp + ".png"; case ECharacterPicPathType.SelectCharacter: name = postCfg.Get(1, id).SelectCharacter; split = name.Split('_'); if (split[1].Equals("SC")) { DebugUtil.Log("该角色使用旧版立绘资源配置:" + id); return @"Assets/Art_Out/UI/Texture/UI_Pic_Main/UI_Poster/Select/" + postCfg.Get(skinID, id).SelectCharacter + ".png"; } else return @"Assets/Art_Out/UI/Texture/UI_Pic_Main/UI_Poster/Bust/" + postCfg.Get(skinID, id).SelectCharacter + ".png"; case ECharacterPicPathType.Poster: return Constants.UI_POSTER_DEFAULT_PATH + postCfg.Get(skinID, id).Poster + ".png"; case ECharacterPicPathType.HeadPic: if (isCommanderHead) return TableManager.Instance.Tables.GlobalConfig.CommanderHeadPath + postCfg.Get(skinID, id).CommanderHeadPath + ".png"; return TableManager.Instance.Tables.GlobalConfig.HeadPicFrontPath + postCfg.Get(skinID, id).PIcHeadPath + ".png"; case ECharacterPicPathType.AssistantPoster: return Constants.UI_POSTER_DEFAULT_PATH + postCfg.Get(1, id).AssistantPoster + ".png"; } return null; } /// /// 获取战斗角色皮肤模型路径 /// /// /// public static string GetFightCharacterModelPath(CharacterDataInfo characterDataInfo) { DataCharacterSkin dataSkin = TableManager.Instance.Tables.SkinCfg.Get((int)characterDataInfo.SkinID, (int)characterDataInfo.ID); if (null == dataSkin) return string.Empty; return PathEx.GetCharacterFightModelPath(dataSkin.NameID, characterDataInfo.Cfg.WeaponId); } /// /// 获取角色皮肤模型路径 /// /// public static string GetCharacterModelPath(CharacterDataInfo characterDataInfo) { DataCharacterSkin dataSkin = TableManager.Instance.Tables.SkinCfg.Get((int)characterDataInfo.SkinID, (int)characterDataInfo.ID); if (null == dataSkin) return string.Empty; return PathEx.GetCharacterDisplayModelPath(dataSkin.NameID); } /// /// 获取角色皮肤模型路径 /// /// public static string GetCharacterModelPath(int SkinID, int RoleID) { DataCharacterSkin dataSkin = TableManager.Instance.Tables.SkinCfg.Get(SkinID, RoleID); if (null == dataSkin) return string.Empty; return PathEx.GetCharacterDisplayModelPath(dataSkin.NameID); } //获取同一角色的皮肤配置列表 public static List GetCharacterSkinCfgList(int uid) { var retList = new List(); var cfg = TableManager.Instance.Tables.SkinCfg; for (int i = 0; i < cfg.DataList.Count; i++) { var dataCfg = cfg.DataList[i]; if (dataCfg.RoleID == uid) { int curIdx = i; while (curIdx < cfg.DataList.Count) { var curDataCfg = cfg.DataList[curIdx]; if (curDataCfg.RoleID != uid) { break; } retList.Add(cfg.DataList[curIdx]); ++curIdx; } break; } } return retList; } public static string GetNPCHeadPicPath(int npcConfigID) { var npcData = TableManager.Instance.Tables.FightNPCConfig.GetOrDefault(npcConfigID); if (npcData != null) { return string.Format(Constants.UI_NPC_ICON_PATH, npcData.Icon); } DebugUtil.LogError($"无法通过ID获取配置表数据,NPCConfigID:{npcConfigID}"); return ""; } public static string GetNPCPosterByID(int npcConfigID) { var npcData = TableManager.Instance.Tables.FightNPCConfig.GetOrDefault(npcConfigID); if (npcData != null) { return Constants.UI_POSTER_DEFAULT_PATH + npcData.Poster + ".png"; } DebugUtil.LogError($"无法通过ID获取配置表数据,NPCConfigID:{npcConfigID}"); return ""; } //} //public static string GetVehiclePath(int id) //{ //} //??????? /// /// 获取本地化文本 /// /// /// public static string GetLocalizeText(string key, bool isUnescape = false) { if (isUnescape) return Regex.Unescape(StringManager.Instance.GetLocalizeTextByKey(key)); // 防止配置的文本中的字符被转义 else return StringManager.Instance.GetLocalizeTextByKey(key); } // public static string GetLocalizeText(string key, float val) // { // return StringManager.Instance.GetLocalizeTextByKey(key, val); // } /// /// 根据养成数据读取角色技能描述文本 /// /// /// public static string GetSkillDesc(CharacterDataInfo characterData) { var id = CharacterDataHelper.GetCharacterSkillId(characterData); //characterData.GetAwakePassiveId() var key = $"{E_LocalizePrefix.skill_desc}_{id}"; return GetLocalizeTextByKey(key, characterData); } /// /// 根据养成数据读取载具技能描述文本 /// /// /// public static string GetSkillDesc(VehicleCultivateData vehicleData) { var id = VehicleDataHelper.GetVehicleSkillId(vehicleData); //characterData.GetAwakePassiveId() var key = $"{E_LocalizePrefix.skill_desc}_{id}"; return GetLocalizeTextByKey(key, vehicleData); } public static string GetSkillDescInBattle(GameUnit unit) { if (LevelManager.Instance.CurrentLevel != null && LevelManager.Instance.CurrentLevel.isInBattle) { int skillID = 0; if (unit is Character.Character character) { skillID = character.runtimeData.configData.skillId; } if (unit is NormalVehicle vehicle) { skillID = vehicle.runtimeData.configData.skillId; } if (skillID == 0) { DebugUtil.LogError($"技能ID为0!unitID:{unit.GetID()}"); return ""; } var key = $"{E_LocalizePrefix.skill_desc}_{skillID}"; return GetLocalizeTextByKey(key, unit); } return ""; } //获取角色觉醒被动技能描述 public static string GetAwakePassiveSkillDesc(CharacterDataInfo characterData) { var awakePassiveSkillID = characterData.GetAwakePassiveId(); var key = $"{E_LocalizePrefix.PassiveSkillDesc}_{awakePassiveSkillID}"; return GetLocalizeTextByKey(key, characterData); } //获取角色觉醒被动技能描述 public static string GetBreakPassiveSkillDesc(CharacterDataInfo characterData) { var breakPassiveSkillID = characterData.GetBreakPassiveId(); var key = $"{E_LocalizePrefix.PassiveSkillDesc}_{breakPassiveSkillID}"; return GetLocalizeTextByKey(key, characterData); } public static string GetLocalizeTextByKey(string key, GameUnit unit) { if (unit == null) { DebugUtil.LogError($"传入的Unit数据为空!"); return ""; } var stringData = TableManager.Instance.Tables.StringConfig.GetOrDefault(key); if (stringData == null) { DebugUtil.LogError($"无法获取文本,StringConfig不包含此key:{key}"); return ""; } switch (stringData.CalculateType) { case DescCalculateType.None: return GetLocalizeText(key); case DescCalculateType.Attack: return StringManager.Instance.GetLocalizeTextByKey(key, unit.fightData.attack); case DescCalculateType.Defend: return StringManager.Instance.GetLocalizeTextByKey(key, unit.fightData.defense); case DescCalculateType.Hp: return StringManager.Instance.GetLocalizeTextByKey(key, unit.aliveData.maxHp); case DescCalculateType.Armor: return StringManager.Instance.GetLocalizeTextByKey(key, unit.aliveData.maxShield); default: return ""; } } /// /// 获取角色技能描述 /// /// /// /// public static string GetLocalizeTextByKey(string key, CharacterDataInfo characterData) { if (characterData == null) { DebugUtil.LogError($"传入的角色数据为空!"); return ""; } var stringData = TableManager.Instance.Tables.StringConfig.GetOrDefault(key); if (stringData == null) { DebugUtil.LogError($"无法获取文本,StringConfig不包含此key:{key}"); return ""; } switch (stringData.CalculateType) { case DescCalculateType.None: return GetLocalizeText(key); case DescCalculateType.Attack: return StringManager.Instance.GetLocalizeTextByKey(key, characterData.Attack()); case DescCalculateType.Defend: return StringManager.Instance.GetLocalizeTextByKey(key, characterData.Defence()); case DescCalculateType.Hp: return StringManager.Instance.GetLocalizeTextByKey(key, characterData.HP()); case DescCalculateType.Armor: return StringManager.Instance.GetLocalizeTextByKey(key, characterData.Armor()); default: return ""; } } public static string GetLocalizeTextByKey(string key, VehicleCultivateData vehicleData) { if (vehicleData == null) { DebugUtil.LogError($"传入的载具数据为空!"); return ""; } var stringData = TableManager.Instance.Tables.StringConfig.GetOrDefault(key); if (stringData == null) { DebugUtil.LogError($"无法获取文本,StringConfig不包含此key:{key}"); return ""; } switch (stringData.CalculateType) { case DescCalculateType.None: return GetLocalizeText(key); case DescCalculateType.Attack: return StringManager.Instance.GetLocalizeTextByKey(key, vehicleData.Attack()); case DescCalculateType.Defend: return StringManager.Instance.GetLocalizeTextByKey(key, vehicleData.Defense()); case DescCalculateType.Hp: return StringManager.Instance.GetLocalizeTextByKey(key, vehicleData.Hp()); case DescCalculateType.Armor: DebugUtil.LogError($"载具没有护甲值!!!StringKey:{key}"); return GetLocalizeText(key); default: return ""; } } /// /// 获取本地化文本前缀+id /// /// /// /// public static string GetLocalizeText(E_LocalizePrefix localizePrefix, int id, bool isUnescape = false) { if (isUnescape) return Regex.Unescape(StringManager.Instance.GetLocalizeTextByKey($"{localizePrefix}_{id}")); // 防止配置的文本中的字符被转义 else return StringManager.Instance.GetLocalizeTextByKey($"{localizePrefix}_{id}"); } public static string GetLocalizeText(E_LocalizePrefix localizePrefix, string key, bool isUnescape = false) { if (isUnescape) return Regex.Unescape(StringManager.Instance.GetLocalizeTextByKey($"{localizePrefix}_{key}")); // 防止配置的文本中的字符被转义 else return StringManager.Instance.GetLocalizeTextByKey($"{localizePrefix}_{key}"); } public static string GetLocalizeText(string key, params object[] param) { string str = StringManager.Instance.GetLocalizeTextByKeyAndParams(key, param); return str; } public static void SetScaleWithCameraOrgSize(GameObject go) { var camera = CameraManager.Instance.MainCamera; var cameraCtrller = camera.gameObject.GetComponent(); var fov = camera.fieldOfView; // int minSize = 6; // if (cameraCtrller) // { // minSize = (int)cameraCtrller.CameraMinSize; // } // // float curSize = camera.orthographicSize; //float mul = minSize / curSize; float mul = 0.5f;//30 / fov; go.transform.localScale = new Vector3(mul, mul, mul); } //图片灰显开启 public static async UniTask OpenImageGray(Image img) { var mat = await AssetManager.Instance.LoadAssetAsync("Assets/Art_Out/UI/Material/mat_GrayUI.mat"); if (mat) { var material = UnityEngine.Object.Instantiate(mat); img.material = material; } } public static async void SetImageGray(Image img, bool isGray) { int param = isGray ? 1 : 0; bool dontHaveGrayMat = true; if (img.material) { if (img.material.shader.name == "NLD_URP/NLD_UI_Gray") { dontHaveGrayMat = false; } } if (dontHaveGrayMat) { await OpenImageGray(img); } img.material.SetInt(ForceGray, param); } public static void ConsoleOpResultError(uint o) { OpResult opResult = (OpResult)o; bool isShowForPlayer = false; DataErrorCfg errorCfg = TableManager.Instance.Tables.ErrorLogCfg.Get((int)o); Debug.LogError($"{GetLocalizeText(E_LocalizePrefix.OpResult, (int)o)}, {GetLocalizeText("errorIdDesc", opResult)}, {o}"); if (null != errorCfg) { isShowForPlayer = errorCfg.IsShowToPlayer; //DebugUtil.LogError("请在errorLog中补上id为{0}的表",o); } if (isShowForPlayer) { if (null != errorCfg) { ShowMessageTips( $"{GetLocalizeText(E_LocalizePrefix.OpResult, (int)o)}"); //, {GetLocalizeText("errorIdDesc", (OpResult)o)}"); } else { //DebugUtil.LogError("提供给用户显示的errorLog没有", o); } } } public static string GetRomanCode(int i)//获取1到6的罗马数字 { switch (i) { case 0: return "0"; case 1: return "I"; case 2: return "II"; case 3: return "III"; case 4: return "IV"; case 5: return "V"; case 6: return "VI"; } DebugUtil.LogError("你要的罗马数字还没有"); return ""; } public static string GetCommonLevelStr(int lv) { bool isHundred = lv / 100 > 0; if (isHundred) { return lv.ToString(); } var left = lv % 100; if (left >= 10) { return "0" + left; } return "00" + left; } public static string GetShootMode(EShootMode shootMode) { switch (shootMode) { case EShootMode.Rapidfire: return GetLocalizeText("Rapidfire"); case EShootMode.Burstfire: return GetLocalizeText("Burstfire"); } DebugUtil.LogError("射击模式{0}没有配本地化,请在stringConfig中配齐", shootMode); return shootMode.ToString(); } public const string BLUR_MAT_PATH = "Assets/Art_Out/UI/Material/NLD_URP_UI_GaussianBlur_low.mat"; public static void CaptureScreenshot(bool captureUI = true) { int width = PerformanceManager.instance.fullScreenWidth; int height = PerformanceManager.instance.fullScreenHeight; if (null == screenTexture) screenTexture = RenderTexturePool.Instance.Create(PerformanceManager.instance.MainRt, width, height, RenderTexturePool.DEFAULT_DEPTH); CameraManager.Instance.SetMainCameraActive(false); // 先渲图 Camera usingCamera = captureUI ? CameraManager.Instance.UICamera : CameraManager.Instance.MainCamera; usingCamera.targetTexture = screenTexture; usingCamera.Render(); usingCamera.targetTexture = captureUI ? null : CameraManager.Instance.DefaultRenderTarget; #region 高斯模糊处理 var material = AssetManager.Instance.GetPreLoadResult(BLUR_MAT_PATH); // 需要用一个缓存的rt,不然移动平台会出现方块 RenderTexture cacheRt = CameraManager.Instance.DefaultRenderTarget; Graphics.Blit(screenTexture, cacheRt, material); Graphics.Blit(cacheRt, screenTexture); #endregion } public static void ScreenshotReset() { CameraManager.Instance.SetMainCameraActive(true); } public static void RefreshCharacter2DPic(Image img, Sprite sprite) { img.gameObject.SetActive(false); //string imgPath = GetCharacterPicPath(roleId, eCharacterPicPathType); //await AssetManager.Instance.LoadAssetAsync(imgPath, spr => // { // img.sprite = spr; // img.gameObject.SetActive(true); // }); img.sprite = sprite; img.gameObject.SetActive(true); } public static int GetGameUnitUltraSkillID(GameUnit unit) { uint uid = unit.GetID(); return GetGameUnitUltraSkillID(uid); } public static int GetGameUnitUltraSkillID(uint uid) { CharacterDataInfo characterDataInfo; if (CharacterDataInfoManager.Instance.DataDic.TryGetValue(uid, out characterDataInfo)) { return CharacterDataHelper.GetCharacterSkillId(characterDataInfo); } DebugUtil.LogError("请检查传入的角色对象uid"); return 0; } public static string GetSkillTargetIcon(int skillID) { var iconName = ""; var skillData = TableManager.Instance.Tables.SkillConfig.GetOrDefault(skillID); if (skillData == null) { DebugUtil.LogError($"无法获取技能表配置,ID:{skillID}"); return ""; } var areaID = skillData.InfluenceAreaId; var influenceData = TableManager.Instance.Tables.AreaConfig.GetOrDefault(areaID); if (influenceData == null) { DebugUtil.LogError($"无法获取InfluenceArea表配置,ID:{areaID}"); return ""; } iconName = influenceData.Icon; return string.IsNullOrEmpty(iconName) ? iconName : Constants.UI_SKILL_TARGET_ICON + iconName; } public static string WWWLoadText(string fileName) { UnityWebRequest www = UnityWebRequest.Get(fileName);//WWW会自动开始读取文件 while (!www.isDone) { }//WWW是异步读取,所以要用循环来等待 return www.downloadHandler.text; } public static string FormatNumber(long num) { return string.Format("{0:N0}", num); } public static string FormatNumber(float num) { return string.Format("{0:N0}", num); } public static string FormatMoney(float num) { return num.ToString("C2"); } public static string FormatSize(float fBytes) { if (fBytes <= 0) { return "0K"; } else if (fBytes < 102.4f) { return "0.1K"; } else if (fBytes < 1024 * 1024) { return string.Format("{0:F1}K", (fBytes / 1024)); } else { return string.Format("{0:F1}M", (fBytes / (1024 * 1024))); } } public static string Validate(string text) { //https://msdn.microsoft.com/en-us/library/20bw873z(v=vs.110).aspx text = RemoveEmoji(text, @"\p{C}"); return text; } static string ValidateEx(string text) { //https://en.wikipedia.org/wiki/Emoji#Emoji_in_the_Unicode_standard // 635 of the 766 codepoints in the Miscellaneous Symbols and Pictographs block are considered emoji. string pattern = @"[^\u1F300-\u1F5FF]"; text = RemoveEmoji(text, pattern); // All of the 15 codepoints in the Supplemental Symbols and Pictographs block are considered emoji. pattern = @"[^\u1F910-\u1F918\u1F980-\u1F984\u1F9C0]"; text = RemoveEmoji(text, pattern); // All of the 80 codepoints in the Emoticons block are considered emoji. // pattern = @"[^\u1F60-\u1F64]"; // text = RemoveEmoji (text, pattern); // 87 of the 98 codepoints in the Transport and Map Symbols block are considered emoji. // pattern = @"[^\u1F68-\u1F6F]"; // text = RemoveEmoji (text, pattern); // 77 of the 256 codepoints in the Miscellaneous Symbols block are considered emoji. // pattern = @"[^\u260-\u26F]"; // text = RemoveEmoji (text, pattern); // 77 of the 256 codepoints in the Miscellaneous Symbols block are considered emoji. // pattern = @"[^\u270-\u27B]"; // text = RemoveEmoji (text, pattern); return text; } static string RemoveEmoji(string text, string pattern) { return System.Text.RegularExpressions.Regex.Replace(text, pattern, string.Empty); } public static void AmendBuildingRotation(Transform building) { var vr = building.localEulerAngles; vr.y %= 360; if (vr.y < 0) { vr.y += 360; } if (vr.y <= 45) { vr.y = 0; } else if (vr.y <= 135) { vr.y = 90; } else if (vr.y <= 225) { vr.y = 180; } else if (vr.y <= 315) { vr.y = 270; } else { vr.y = 0; } building.localRotation = Quaternion.Euler(vr); } public static long TotalSeconds() { TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)); return Convert.ToInt64(ts.TotalSeconds); } public static long TotalMilliseconds() { TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)); return Convert.ToInt64(ts.TotalMilliseconds); } public static double Countdown(DateTime dt) { TimeSpan ts = (dt - DateTime.UtcNow); return ts.TotalSeconds; } public static double Countdown(long seconds) { TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)); return seconds - ts.TotalSeconds; } public static DateTime ParseTimeFromNow(long countdown) { return DateTime.UtcNow.AddSeconds(countdown); } public static double PastTime(DateTime pastTime) { TimeSpan ts = (DateTime.UtcNow - pastTime); return ts.TotalSeconds; } public static int GetDayBySeconds(long seconds) { return (int)Mathf.Floor(seconds / (3600 * 24)); } public static bool IsSameDay(long seconds1, long seconds2) { return GetDayInterval(seconds1, seconds2) == 0; } public static int GetDayInterval(long seconds1, long seconds2) { int day1 = GetDayBySeconds(seconds1); int day2 = GetDayBySeconds(seconds2); return Mathf.Abs(day1 - day2); } //获取第二天凌晨时间戳 public static long GetTomorrowTimestamp() { DateTime tomorrow = DateTime.UtcNow.AddDays(1); DateTime tomorrowMidnight = new DateTime(tomorrow.Year, tomorrow.Month, tomorrow.Day, 0, 0, 0, 0, DateTimeKind.Utc); DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); TimeSpan diff = tomorrowMidnight.ToUniversalTime() - origin; return (long)Math.Floor(diff.TotalSeconds); } public static string GetDateString() { return DateTime.Now.ToString(); } /// /// 获取一个随机列表 /// /// /// /// public static IList GetRandomList(int beginInt, int endInt) { int count = endInt - beginInt + 1; IList arr = new int[count]; for (int i = 0; i < count; i++) { arr[i] = beginInt + i; } Shuffle(arr); return arr; } /// /// Array to string. split with , /// /// formatted string. /// Array. /// The 1st type parameter. public static string ArrayToString(T[] array) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); if (array != null && array.Length > 0) { for (int i = 0; i < array.Length; i++) { if (i != 0) { sb.Append(','); } sb.Append(array[i]); } } return sb.ToString(); } /// /// 获取当前时间戳(毫秒) /// /// public static long GetTimeStamp() { // DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); DateTime startTime = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Local);// 当地时区 return (long)(DateTime.Now - startTime).TotalMilliseconds; } /// /// 获取指定时间的时间戳(毫秒) /// /// public static long GetTimeStamp(DateTime date) { DateTime startTime = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), date.Kind == DateTimeKind.Utc ? TimeZoneInfo.Utc : TimeZoneInfo.Local); return (long)(date - startTime).TotalMilliseconds; } /// /// 获取当前时间戳(秒) /// /// public static long GetTimeStampSeconds() { DateTime startTime = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Local);// 当地时区 return (long)(DateTime.Now - startTime).TotalSeconds; } public static string GetTimeString(string format, int seconds) { string label = format; int ms = seconds * 1000; int s = seconds; int m = s / 60; int h = m / 60; int d = h / 24; string t = ""; //处理天 if (label.Contains("%dd")) { t = d >= 10 ? d.ToString() : ("0" + d.ToString()); label = label.Replace("%dd", t); h = h % 24; } else if (label.Contains("%d")) { label = label.Replace("%d", d.ToString()); h = h % 24; } //处理小时 if (label.Contains("%hh")) { t = h >= 10 ? h.ToString() : ("0" + h.ToString()); label = label.Replace("%hh", t); m = m % 60; } else if (label.Contains("%h")) { label = label.Replace("%h", h.ToString()); m = m % 60; } //处理分 if (label.Contains("%mm")) { t = m >= 10 ? m.ToString() : ("0" + m.ToString()); label = label.Replace("%mm", t); s = s % 60; } else if (label.Contains("%m")) { label = label.Replace("%m", m.ToString()); s = s % 60; } //处理秒 if (label.Contains("%ss")) { t = s >= 10 ? s.ToString() : ("0" + s.ToString()); label = label.Replace("%ss", t); ms = ms % 1000; } else if (label.Contains("%s")) { label = label.Replace("%s", s.ToString()); ms = ms % 1000; } //处理毫秒 if (label.Contains("ms")) { t = ms.ToString(); label = label.Replace("%ms", t); } return label; } // 把一个记录的时间戳转换成日期显示(毫秒) public static string GetTimeStampDateString(double timeStamp, string format = "yyyy-MM-dd HH:mm:ss") { // var offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); var offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now); var dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Add(offset).AddMilliseconds(timeStamp); return dt.ToString(format); } public static T ArrayFind(T[] array, Predicate condition) { T item = default(T); if (array != null && array.Length > 0) { for (int i = 0; i < array.Length; i++) { if (condition(array[i])) { item = array[i]; break; } } } return item; } public static int ArrayFindIndex(T[] array, Predicate condition) { int index = -1; if (array != null && array.Length > 0) { for (int i = 0; i < array.Length; i++) { if (condition(array[i])) { index = i; break; } } } return index; } public static T[] ArrayAdd(T[] array, T item) { List newArray = new List(); if (array != null) { newArray.AddRange(array); } newArray.Add(item); return newArray.ToArray(); } public static int RandomByWeight(Dictionary idWeights) { int weights = 0; int id = 0; foreach (var kv in idWeights) { weights += kv.Value; id = kv.Key; } int pos = UnityEngine.Random.Range(0, weights); weights = 0; foreach (var kv in idWeights) { weights += kv.Value; if (pos < weights) { id = kv.Key; break; } } return id; } public static int RandomByWeight(List weightList) { int weights = 0; int idx = 0; for (int i = 0; i < weightList.Count; i++) { weights += weightList[i]; } int pos = UnityEngine.Random.Range(0, weights); weights = 0; for (int i = 0; i < weightList.Count; i++) { weights += weightList[i]; if (pos < weights) { idx = i; break; } } return idx; } public static int RandomByWeight(int[] weightList) { int weights = 0; int idx = 0; for (int i = 0; i < weightList.Length; i++) { weights += weightList[i]; } int pos = UnityEngine.Random.Range(0, weights); weights = 0; for (int i = 0; i < weightList.Length; i++) { weights += weightList[i]; if (pos < weights) { idx = i; break; } } return idx; } /// /// 用K、M、G等单位表示数字,不包含小数点,英文计数法 /// /// /// public static string ToMetricNotation(double number) { if (number >= 1_000_000_000) return (number / 1_000_000_000).ToString("0") + "G"; else if (number >= 1_000_000) return (number / 1_000_000).ToString("0") + "M"; else if (number >= 1_000) return (number / 1_000).ToString("0") + "K"; else return number.ToString(); } /// /// 输出格式化的数字字符串 /// /// /// public static string ToFormatNumber(double number) { return number.ToString("N0", CultureInfo.CurrentCulture); } public static void JumpToAnimation(Animator animator, string stateName, float normalizedTime, int layer = -1) { animator.Play(stateName, layer, normalizedTime); } public static string GetLevelDisplay(int levelId) { //潜规则,策划修改为301 - 但需要显示为1 int lv = levelId % 100; return lv.ToString(); } /// /// Gets the ADIDB y platform async. /// /// Application.AdvertisingIdentifierCallback回调参数一共有三:string adid, bool 是否成功 , string error. public static void GetADIDByPlatformAsync(Application.AdvertisingIdentifierCallback callback) { Application.RequestAdvertisingIdentifierAsync(callback); } public static string PlayerIdToString(ulong playerId) { return (playerId + 0xb2c3d4).ToString("x"); } public static ulong StringToPlayerId(string str) { ulong playerId = Convert.ToUInt64(str, 16); playerId -= 0xb2c3d4; return playerId; } public static void SaveToLocal(string key, string data) { byte[] encryptData = RijndaelManager.Instance.EncryptStringToBytes(data); PlayerPrefs.SetString(key, System.Convert.ToBase64String(encryptData)); } public static string ReadFromLocal(string key, string defaultData = "") { if (PlayerPrefs.HasKey(key)) { byte[] encryptData = System.Convert.FromBase64String(PlayerPrefs.GetString(key)); defaultData = RijndaelManager.Instance.DecryptStringFromBytes(encryptData); } return defaultData; } public static NameValueCollection ParseQueryString(string s) { NameValueCollection nvc = new NameValueCollection(); // remove anything other than query string from url if (s.Contains("?")) { s = s.Substring(s.IndexOf('?') + 1); } foreach (string vp in Regex.Split(s, "&")) { DebugUtil.Log("vp = {0}", vp); string[] singlePair = Regex.Split(vp, "="); if (singlePair.Length == 2) { DebugUtil.Log("key = {0} value = {1}", singlePair[0], singlePair[1]); nvc.Add(singlePair[0], singlePair[1]); } else { DebugUtil.Log("key = {0} value = null", singlePair[0]); // only one key with no value specified in query string nvc.Add(singlePair[0], string.Empty); } } return nvc; } public static string GetMD5Hash(string input) { // step 1, calculate MD5 hash from input MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); byte[] hash = md5.ComputeHash(inputBytes); // step 2, convert byte array to hex string StringBuilder sb = new StringBuilder(); for (int i = 0; i < hash.Length; i++) { sb.Append(hash[i].ToString("X2")); } return sb.ToString(); } /// /// 判断是否是磁盘空间已满异常 /// /// /// public static bool IsDiskFull(Exception ex) { if (ex == null) { return false; } const int HR_ERROR_HANDLE_DISK_FULL = unchecked((int)0x80070027); const int HR_ERROR_DISK_FULL = unchecked((int)0x80070070); return ex.HResult == HR_ERROR_HANDLE_DISK_FULL || ex.HResult == HR_ERROR_DISK_FULL; } /// /// 格式化json /// /// /// public static string ConvertJsonString(string str) { JsonSerializer serializer = new JsonSerializer(); TextReader tr = new StringReader(str); JsonTextReader jtr = new JsonTextReader(tr); object obj = serializer.Deserialize(jtr); if (obj != null) { StringWriter textWriter = new StringWriter(); JsonTextWriter jsonWriter = new JsonTextWriter(textWriter) { Formatting = Formatting.Indented, Indentation = 4, IndentChar = ' ' }; serializer.Serialize(jsonWriter, obj); return textWriter.ToString(); } else { return str; } } /// /// 将秒转化为x小时x分x秒格式 /// /// /// /// public static string GetTimeDescStr(int seconds) { string retStr = ""; int h = seconds / 3600; int m = (seconds - h * 3600) / 60; int s = seconds - h * 3600 - m * 60; if (h > 0) { if (s > 0) { retStr = GetLocalizeText("time_hour_min_sec", h, m, s); } else if (m > 0) { retStr = GetLocalizeText("time_hour_min", h, m); } else { retStr = GetLocalizeText("time_hour", h); } } else { if (m > 0) { if (s > 0) { retStr = GetLocalizeText("time_min_sec", m, s); } else { retStr = GetLocalizeText("time_min", m); } } else { retStr = GetLocalizeText("time_sec", s); } } return retStr; } //转换为英文缩写 public static string NumToEnglish(uint value) { if (value > 10000 && value <= 10000000) { return string.Format("{0}K", (value / 1000).ToString()); } else if (value > 10000000) { return string.Format("{0}M", (value / 1000000).ToString()); } else { return value.ToString(); } } public static float CheckAngle(float value) { float angle = value - 180; if (angle > 0) return angle - 180; return angle + 180; } public static int GetTransformIndex(Transform transform) { var parent = transform.parent; if (parent != null) { var childCount = parent.childCount; for (int i = 0; i < childCount; i++) { var child = parent.GetChild(i); if (child == transform) return i; } } return -1; } /// /// 预加载或卸载环境天气图标 /// /// public static void PreLoadOrUnloadEnvironmentWeatherDayNightIcon(bool loadOrUnload) { List paths = new(); foreach (ELevelTerrainType value in Enum.GetValues(typeof(ELevelTerrainType))) { ELevelTerrainType enumValue = value; DataEnviorment config = GetEnvironmentConfig(enumValue); paths.Add(config.Icon); } foreach (WeatherType value in Enum.GetValues(typeof(WeatherType))) { WeatherType enumValue = value; DataEnWeather config = GetWeatherConfig(enumValue); paths.Add(config.Icon); } foreach (DayNightType value in Enum.GetValues(typeof(DayNightType))) { DayNightType enumValue = value; DataDayNightProp config = GetDayNightConfig(enumValue); paths.Add(config.Icon); } foreach (string iconPath in paths) { if (loadOrUnload) AssetManager.Instance.PostPreload(iconPath).Forget(); else AssetManager.Instance.Unload(iconPath); } } /// /// 预加载或卸载战役评级图标 /// /// public static void PreLoadOrUnloadWarRatingIcon(bool loadOrUnload) { foreach (E_WarRating value in Enum.GetValues(typeof(E_WarRating))) { E_WarRating enumValue = value; if (loadOrUnload) { AssetManager.Instance.PostPreload(GetWarRatingIconPath(enumValue)).Forget(); AssetManager.Instance.PostPreload(GetReachedWarRatingIconPath(enumValue)).Forget(); } else { AssetManager.Instance.Unload(GetWarRatingIconPath(enumValue)); AssetManager.Instance.Unload(GetReachedWarRatingIconPath(enumValue)); } } } /// /// 获取战役评级图标路径 /// /// /// public static string GetWarRatingIconPath(E_WarRating warRating) { return $"Assets/Art_Out/UI/Texture/LevelSelectNew/War/UI_{warRating}.png"; } /// /// 获取战役已达到的评级图标路径 /// public static string GetReachedWarRatingIconPath(E_WarRating warRating) { return $"Assets/Art_Out/UI/Texture/LevelSelectNew/War/UI_{warRating}_On.png"; } public static DataEnWeather GetWeatherConfig(WeatherType weatherType) { var result = TableManager.Instance.Tables.WeatherConfig.Get((int)weatherType); return result; } public static DataEnviorment GetEnvironmentConfig(ELevelTerrainType eLevelTerrainType) { var result = TableManager.Instance.Tables.EnviormentConfig.Get((int)eLevelTerrainType); return result; } public static DataDayNightProp GetDayNightConfig(DayNightType dayNightType) { var result = TableManager.Instance.Tables.DayNightProp.Get((int)dayNightType); return result; } public static void AddItem(ref List sumItem, cfg.item.ItemCounts item1) { for (int i = 0; i < sumItem.Count; i++) { if (sumItem[i].Id == item1.Id) { sumItem[i] = new cfg.item.ItemCounts(sumItem[i].Id, sumItem[i].Count + item1.Count); return; } } sumItem.Add(item1); } public static cfg.item.ItemCounts ItemXNumber(cfg.item.ItemCounts item, int number) { return new cfg.item.ItemCounts(item.Id, item.Count * number); } public static string GetVehicleBonusStr(BonusType btype) { switch (btype) { case BonusType.Hp: return GetLocalizeText("cultivate_Hp"); case BonusType.SkillLv: return GetLocalizeText("vehicleCultivate_skillLv"); case BonusType.MoveSpeed: return GetLocalizeText("cultivate_Speed"); case BonusType.SeatCount: return GetLocalizeText("vehicleCultivate_PersonNum"); case BonusType.AttackPercent: return GetLocalizeText("vehicleCultivate_AttackPercent"); case BonusType.AttackShiledScale: return GetLocalizeText("vehicleCultivate_AttackShiledScale"); case BonusType.HpPercent: return GetLocalizeText("cultivate_Hp"); case BonusType.AttackHpScale: return GetLocalizeText("vehicleCultivate_AttackHpScale"); default: DebugUtil.LogError("没有这个类型的奖励文本: " + btype + ",请在此处配置"); return string.Empty; } } public static void ShowMessageTips(string TipsMsg) { UITipsManager.ShowTips(TipsMsg); } public static void SetActive(GameObject obj, bool isActive) { if (isActive) { obj.transform.localScale = Vector3.one; } else { obj.transform.localScale = Vector3.zero; } } // /// // /// 要保证所有网格能对齐,需要调整网格的列数和行数,规则是column必须是偶数,row必须是偶数且必须是奇数的两倍 // /// 这样能保证网格一定对齐 // /// // /// // /// // public static void CorrectTGSColumnAndRow(ref int column, ref int row) // { // if (column % 2 != 0) // { // column--; // } // // var halfRow = row / 2; // if (halfRow % 2 == 0) // { // halfRow++; // } // // row = halfRow * 2; // } /// /// 获得Tgs中长度对应的六边形数量 /// /// 总长度 /// 六边形对角线长度 /// 是否对角线朝向排列 /// public static int GetHexCount(float totalLength, float hexDiagonalLength, bool isDiagonal) { if (isDiagonal) return Mathf.FloorToInt((4 * totalLength) / (3 * hexDiagonalLength) - 1 / 3f); else { var sqrt3 = Mathf.Sqrt(3); var countInFloat = (totalLength - (sqrt3 / 4 * hexDiagonalLength)) / (Mathf.Sqrt(3) / 2 * hexDiagonalLength); return Mathf.FloorToInt(countInFloat); } } public static bool IsInGame() { return Application.isPlaying && Main.Instance.isInited; } /// /// 设置uint的某一位,返回int /// /// 被设置的数据 /// 第idx位 /// true为0, false为1 public static int GetIntBitByIndex(uint data, int idx, bool flag) { if (idx > 31 || idx < 0) { return (int)data; } if (!flag) { data |= (uint)(1 << idx); } else { data &= ~(uint)(1 << idx); } return (int)data; } public static string GetItemDisPlayName(int id) { DataItem itemcfg = TableManager.Instance.Tables.Item.Get(id); if (itemcfg == null) { DebugUtil.LogError("该物体不存在:" + id); return ""; } return "";//等配置,延后 } /// /// 随机抽取 /// /// /// /// /// public static T GetRandomItem(IList list, bool removeItem = false) { if (list == null || list.Count == 0) return default; int randomIndex = Random.Range(0, list.Count); T result = list[randomIndex]; if (removeItem) list.RemoveAt(randomIndex); return result; } /// /// 随机不重复的取一定数量的物体 /// /// /// 全部物体序列 /// 要取的数量 /// public static T[] GetRandomItems(IList list, int count) { if (list == null) { DebugUtil.LogError("空数据"); return null; } if (list.Count < count) { DebugUtil.LogError("数量错误"); return null; } if (count <= 0) return new T[0]; IList listValue = new T[count]; Shuffle(list); for (int i = 0; i < listValue.Count; ++i) { listValue[i] = list[i]; } return (T[])listValue; } /// /// 洗牌算法打乱顺序 /// /// /// /// public static void Shuffle(IList list) { if (list == null) { DebugUtil.LogError("空数据"); return; } for (int i = list.Count - 1; i >= 0; --i) { int index = Random.Range(0, i + 1); if (index == i) continue; (list[index], list[i]) = (list[i], list[index]); } } public static T GetSceneRootComponent(Scene scene) where T : Component { return scene.GetRootGameObjects().FirstOrDefault(root => root.GetComponent() != null)?.GetComponent(); } public class UISceneResult { public UIWindow uiWindow { get; private set; } public SceneHandle sceneHandle { get; private set; } public UISceneResult(UIWindow uiWindow, SceneHandle sceneHandle) { this.uiWindow = uiWindow; this.sceneHandle = sceneHandle; } } /// /// 打开带场景的UI,此函数会处理多场景渲染和主相机逻辑 /// 必须和CloseUIWithScene成对使用 /// /// /// /// /// 是否先打开加载UI /// 加载场景结束后,加载UI前的回调 /// public static async UniTask OpenUIWithScene(string uiName, string scenePath, LoadSceneMode loadSceneMode = LoadSceneMode.Additive, Action loadSceneFinish = null) { //隐藏上层UI //UIManager.Instance.HideAllUI(UINameConst.UI_LoadingInterface, UINameConst.UI_LoadingProgressInterface); SceneHandle sceneHandle = await GameSceneHelper.Instance.LoadSceneForUIView(scenePath, loadSceneMode); if (sceneHandle == null) { DebugUtil.LogError($"加载场景失败!scenePath:{scenePath}"); return null; } loadSceneFinish?.Invoke(sceneHandle); //加载UI UIWindow window = await UIManager.Instance.CreateAndOpenWindow(uiName); return new UISceneResult(window, sceneHandle); } //关闭带场景的UI //必须和OpenUIWithScene成对使用 public static async UniTask CloseUIWithScene(string uiName) { await GameSceneHelper.Instance.UnloadSceneForUIView(); UIManager.Instance.CloseWindow(uiName); UIManager.Instance.ShowAllUI(); } /// /// 切换场景 /// /// public static void ChangeUIScene(string path) { GameSceneHelper.Instance.ChangeSceneForUIView(path); } /// /// 通用按钮监听绑定 /// /// /// /// /// public static GameObject BindButton(Button button, Action action, bool playAudio = true) { if (null == button) { DebugUtil.LogError("传入按钮为空,请检查按钮绑定参数!!!"); return null; } button.onClick.AddListener(() => { if (UIManager.IsClickDisabled) { return; } UIManager.Instance.OnClick(); if (playAudio) { var clickAudio = button.GetComponent(); if (clickAudio) { AudioManager.Instance.PlayAudio(clickAudio.AudioKey); } } action?.Invoke(); }); return button.gameObject; } public static void ClearBind(Button button) { if (null == button) { DebugUtil.LogError("传入按钮为空,请检查按钮绑定参数!!!"); return; } button.onClick.RemoveAllListeners(); } /// /// 按概率随机一个布尔值 /// /// 随机到true的概率,0f~1f /// public static bool RandomBool(float probability) { return Random.Range(0f, 1f) <= probability; } public static void SetImageGrayByChangeColor(Image image, bool isGray) { if (isGray) { image.color = new Color((float)156 / (float)255, (float)156 / (float)255, (float)155 / (float)255); } else { image.color = new Color(1, 1, 1); } } public static string GetCharacterShowModelPath(uint uid) { var dic = CharacterDataInfoManager.Instance.DataDic; if (dic.TryGetValue(uid, out var data)) { var skinID = data.SkinID > 0 ? (int)data.SkinID : Constants.DEFULT_SKINID; var skinCfg = TableManager.Instance.Tables.SkinCfg.Get(skinID, data.Cfg.RoleID); if (skinCfg != null) { var prefabPath = PathEx.GetCharacterDisplayModelPath(skinCfg.NameID); return prefabPath; } } return null; } public static string GetVehicleShowModelPath(uint uid) { var vehicleDataDic = VehicleCultivateDataManager.Instance.DataDic; if (vehicleDataDic.TryGetValue(uid, out var vehicleData)) { if (vehicleData != null) { var prefabPath = PathEx.GetVehicleGameModelPath(vehicleData.Cfg.ID); return prefabPath; } } return null; } /// /// 获取技能图标路径 /// /// /// public static string GetSkillIconByID(int skillID) { var table = TableManager.Instance.Tables.SkillConfig?.Get(skillID); if (table == null) { DebugUtil.LogError("SkillConfig表找不到对应ID配置,ID: " + skillID); return ""; } return Constants.UI_Cultivata_skillIconFolder + table.IconPath; } /// /// 设置主场景相机机位 /// /// public static void SetCurMainSceneCameraStand(int CameraIndex) { List _allCameraStand = new(); var mainSceneHandle = GameSceneHelper.Instance.GetCurrentUIViewScene(); if (mainSceneHandle == null) { DebugUtil.LogError("mainsceneHandle is null"); return; } var cameraStands = mainSceneHandle.Scene.GetRootGameObjects() .FirstOrDefault(go => go.name == "CameraStands"); if (cameraStands == null) { DebugUtil.LogError("cameraStands is null"); return; } _allCameraStand.AddRange(cameraStands.GetComponentsInChildren()); if (CameraIndex > _allCameraStand.Count) { DebugUtil.LogError("Index out of List CameraStands count: " + CameraIndex); return; } _allCameraStand[CameraIndex].Apply(); DebugUtil.Log("已设置主场景相机机位,请注意更新运镜动画timeline"); } /// /// 判断是否客户端显示的道具 /// /// /// public static bool CheckItemIsClientDisplay(int itemID) { var itemCfg = TableManager.Instance.Tables.Item.Get(itemID); if (itemCfg == null) { DebugUtil.LogError("检测客户端是否显示,道具表无法找到配置,id:" + itemID); return false; } return itemCfg.Type == ItemType.Character || itemCfg.Type == ItemType.Normal || itemCfg.Type == ItemType.Useable || itemCfg.Type == ItemType.Vehicle; } /// /// 过滤奖励道具列表,取出不显示的列表 /// /// public static RewardItemList GetFilterRewardItemList(Reward reward) { var list = new RewardItemList(reward.ID); var itemList = reward.ItemList.Get(); for (int i = 0; i < itemList.Count; i++) { var item = itemList[i]; if (CheckItemIsClientDisplay(item.ID)) { list.AddItem(item.ID, item.Count); } } return list; } public static List GetFilterRewardItemList(List rewardIDList) { var list = new List(); for (int i = 0; i < rewardIDList.Count; i++) { var reward = RewardManager.Instance.Get(rewardIDList[i]); var itemList = reward.ItemList.Get(); for (int j = 0; j < itemList.Count; j++) { var item = itemList[i]; if (CheckItemIsClientDisplay(item.ID)) { var it = list.Find(t => t.ID == item.ID); if (it == null) { list.Add(new(item.ID, item.Count)); continue; } it.Count += item.Count; } } } return list; } public static List GetFilterRewardItemList(List itemList) { var retItemList = new List(); for (int i = 0; i < itemList.Count; i++) { var item = itemList[i]; if (CheckItemIsClientDisplay(item.ID)) { retItemList.Add(item); } } return retItemList; } public static void FilterListItem(ListItem listItem) { for (int i = listItem.Length - 1; i >= 0; i--) { var item = listItem.List[i]; if (!CheckItemIsClientDisplay(item.ID)) { listItem.List.RemoveAt(i); listItem.Ids.RemoveAt(i); listItem.Counts.RemoveAt(i); } } } /// /// 获取关卡奖励 /// /// /// public static ItemList GetLevelRewardFilterItemList(ItemList itemList) { var retItemList = new ItemList(); for (int i = 0; i < itemList.Lists.Length; i++) { var itemCounts = itemList.Lists[i]; if (i == (int)ItemSource.LevelPassFirst || i == (int)ItemSource.LevelPassNormal || i == (int)ItemSource.LevelPassStar1 || i == (int)ItemSource.LevelPassStar2 || i == (int)ItemSource.LevelPassStar3) { for (int j = 0; j < itemCounts.Ids.Count; j++) { var id = itemCounts.Ids[j]; var count = itemCounts.Counts[j]; retItemList.Set((uint)i, id, count); } } } return retItemList; } public static bool CheckIsCharacterMaxLevel(uint uid) { if (CharacterDataInfoManager.Instance.DataDic.TryGetValue(uid, out var characterDataInfo)) { var level = characterDataInfo.Level; var breakCfg = TableManager.Instance.Tables.CharacterBreak; var dataBreak = breakCfg.Get((int)characterDataInfo.Cfg.RoleID, (int)characterDataInfo.BreakLevel); var maxLevel = dataBreak.LevelLimit; //var cfg = TableManager.Instance.Tables.CharacterLevelExp.DataList; if (level >= maxLevel) { return true; } } return false; } public static string GetCurLevelTypeStr() { var levelInfo = LevelManager.Instance.CurrLevel; var levelGroup = levelInfo.GroupInfo; string lvTypeStr = ""; switch (levelGroup.Cfg.LevelDifficulty) { case E_LevelDifficulty.Easy: { lvTypeStr = GetLocalizeText("level_type_easy"); break; } case E_LevelDifficulty.Hard: { lvTypeStr = GetLocalizeText("level_type_hard"); break; } /*case E_LevelDifficulty.Plot: { lvTypeStr = GetLocalizeText("level_type_plot"); break; } case E_LevelDifficulty.Resource: { lvTypeStr = GetLocalizeText("level_type_resource"); break; }*/ default: break; } return lvTypeStr; } /// /// 新手引导阶段完成专属事件打点 /// /// public static void GuideStepBiEvent(string stepName) { #if SDK_TALKINGDATA //BIManager.Instance.TrackEvent(BIManager.BI_Guide, new Dictionary //{ // {stepName, 1 } //}); //TD 引导专属事件打点 BIManager.Instance.TrackEvent(TalkingDataEventName.GuideFinish, param1: stepName); #endif } /// /// 新手引导打点 /// /// 引导ID /// 标识引导开始(0)或结束(1) public static void GuideStepBiEvent(int GuideID, int step) { #if SDK_TALKINGDATA BIManager.Instance.TrackEvent("guide_step", new Dictionary { {"guide_id",GuideID }, {"guide_event",step } }); #endif } /// /// 世界坐标转UI坐标 /// /// /// public static Vector2 World2UIPos(Vector3 worldPos) { var viewPortPos = CameraManager.Instance.MainCamera.WorldToViewportPoint(worldPos); var posX = viewPortPos.x * UIManager.Instance.Size.x; var posY = viewPortPos.y * UIManager.Instance.Size.y; var uiPos = new Vector3(posX, posY, 0); return uiPos; } public static string GetCommandSkillIcon(int skillID) { DataPlayerSkill dataPlayerSkill = TableManager.Instance.Tables.PlayerSkillConfig.Get(skillID); if (dataPlayerSkill == null) { DebugUtil.LogError($"指挥官技能表ID:{skillID}不存在!"); return ""; } string iconPath = $"{Framework.Constants.UI_PlaySkill_IconPathFolder}{dataPlayerSkill.IconPath}.png"; return iconPath; } /// /// 这是一个临时的方法,用于获取材质球 /// /// /// public static async UniTask GetVehiclePaintMaterial(string paintPath) { Material ret = null; #if UNITY_EDITOR ret = AssetDatabase.LoadAssetAtPath(paintPath); #else ret = await AssetManager.Instance.LoadAssetAsync(paintPath); #endif //ret = await AssetManager.Instance.LoadAssetAsync(paintPath); if (ret == null) { DebugUtil.LogError("找不到材质球:" + paintPath); } return ret; } static DateTime _GetNextWeekday(DateTime start, DayOfWeek day) { // 计算距离下一个指定星期几的天数(当前已经是星期几则为0) int daysToAdd = ((int)day - (int)start.DayOfWeek + 7) % 7; // 如果当天已经是目标星期几,则跳到下周 // if (daysToAdd == 0) // { // daysToAdd = 7; // } return start.AddDays(daysToAdd); } public static DateTime GetScheduleStartDateTime(int scheduleID) { var scheduleCfg = TableManager.Instance.Tables.Schedule.GetOrDefault(scheduleID); if (scheduleCfg == null) { DebugUtil.LogError($"传入的时间表ID有误, ID:{scheduleID}"); return default; } var timeStr = scheduleCfg.StartTime; var startDay = scheduleCfg.StartDayValue; bool success = DateTime.TryParse(timeStr, out var dateTime); var now = GetCurTime(E_TimeType.Server); var startDayOfWeek = (DayOfWeek)startDay; if (success) { DateTime nextWeekDay = _GetNextWeekday(now, startDayOfWeek); nextWeekDay = new DateTime(nextWeekDay.Year, nextWeekDay.Month, nextWeekDay.Day, dateTime.Hour, dateTime.Minute, dateTime.Second); return nextWeekDay; } DebugUtil.LogError($"Schedule表StartTime配置有误,ID:{scheduleID},StartTime:{dateTime}"); return default; } public static DateTime GetScheduleEndDateTime(int scheduleID) { var scheduleCfg = TableManager.Instance.Tables.Schedule.GetOrDefault(scheduleID); if (scheduleCfg == null) { DebugUtil.LogError($"传入的时间表ID有误, ID:{scheduleID}"); return default; } var timeStr = scheduleCfg.EndTime; var endDay = scheduleCfg.EndDayValue; bool success = DateTime.TryParse(timeStr, out var dateTime); var now = GetCurTime(E_TimeType.Server); var endDayOfWeek = (DayOfWeek)endDay; if (success) { DateTime nextWeekDay = _GetNextWeekday(now, endDayOfWeek); nextWeekDay = new DateTime(nextWeekDay.Year, nextWeekDay.Month, nextWeekDay.Day, dateTime.Hour, dateTime.Minute, dateTime.Second); return nextWeekDay; } DebugUtil.LogError($"Schedule表StartTime配置有误,ID:{scheduleID},StartTime:{dateTime}"); return default; } #region 军团战 /// /// 获取军团战据点背景 /// /// public static string GetLegionBattleBaseBgPath(BuildingType buildingType) { switch (buildingType) { case BuildingType.Granary: // 粮仓 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_base_green.png"; } case BuildingType.Fortification: // 工事 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_base_yellow.png"; } case BuildingType.Blockhouse: // 碉堡 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_base_red.png"; } case BuildingType.Hospital: // 医院 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_base_blue.png"; } case BuildingType.Fortress: // 要塞 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_base_fort01.png"; } default: { DebugUtil.LogError($"未处理类型:{buildingType}"); return string.Empty; } } } /// /// 获取军团战据点图标 /// /// public static string GetLegionBattleBaseIconPath(BuildingType buildingType) { switch (buildingType) { case BuildingType.Granary: // 粮仓 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_icon_forage.png"; } case BuildingType.Fortification: // 工事 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_icon_shield.png"; } case BuildingType.Blockhouse: // 碉堡 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_icon_bullet.png"; } case BuildingType.Hospital: // 医院 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_icon_plus.png"; } case BuildingType.Fortress: // 要塞 { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_icon_fort.png"; } default: { DebugUtil.LogError($"未处理类型:{buildingType}"); return string.Empty; } } } /// /// 获取军团战大本营图标背景 /// /// /// public static string GetLegionBattleBaseBgPath(BattlefieldActorCamp camp) { switch (camp) { case BattlefieldActorCamp.CampA: { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_base_self.png"; } case BattlefieldActorCamp.CampB: { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_base_enemy.png"; } default: { DebugUtil.LogError($"未处理类型:{camp}"); return string.Empty; } } } /// /// 获取军团战大本营图标 /// /// /// public static string GetLegionBattleBaseIconPath() { return "Assets/Art_Out/UI/Texture/LegionBattleMapInfo/UI_icon_camp.png"; } /// /// 获取军团战统一的据点名 /// /// /// public static string GetLegionBattleBaseName(BuildingType type) { return GetLocalizeText(type switch { BuildingType.Granary => "legionbattle_Granary", // 粮仓 BuildingType.Fortification => "legionbattle_Stronghold", // 工事 BuildingType.Blockhouse => "legionbattle_Bunker", // 碉堡 BuildingType.Hospital => "legionbattle_Medical Station", // 医院 BuildingType.Fortress => "legionbattle_Fortress", // 要塞 _ => "None", }); } #endregion /// /// 用指定颜色显示固定位数字符串,不足部分用0部位 /// /// 要显示的数字 /// 要显示的位数 /// 要显示的数字用什么颜色 /// public static string GetShowFixedDigitInteger(int number, int digit, Color color) { string numberText = number.ToString(); // 确定补位部分和其余部分 int length = numberText.Length; if (length < digit) return new string('0', digit - length) + $"{numberText}"; else return $"{numberText[..digit]}"; } /// /// 获取怪物职业 /// /// /// public static Ejob GetMonsterJob(int id) { var monsterConfig = TableManager.Instance.Tables.Monster.GetOrDefault(id); if (monsterConfig == null) return Ejob.Job_Other; if (monsterConfig.NpcType == 1) return Ejob.Job_Vehicle; var monsterClassConfig = TableManager.Instance.Tables.MonsterClass.GetOrDefault(monsterConfig.MonsterClassID); return monsterClassConfig?.Job ?? Ejob.Job_Other; } /// /// 关卡详情 根据职业获取对应图标 /// public static string GetJobIconPath(Ejob job) { return job switch { Ejob.Job_Commander => string.Format(Constants.UI_LEVEL_DETAIL_ICON, "Command"), Ejob.Job_Scout => string.Format(Constants.UI_LEVEL_DETAIL_ICON, "Detective"), Ejob.Job_Shoot => string.Format(Constants.UI_LEVEL_DETAIL_ICON, "Sniper"), Ejob.Job_Support => string.Format(Constants.UI_LEVEL_DETAIL_ICON, "Support"), Ejob.Job_Suppress => string.Format(Constants.UI_LEVEL_DETAIL_ICON, "Suppress"), Ejob.Job_Vehicle => string.Format(Constants.UI_LEVEL_DETAIL_ICON, "Vehicle"), _ => "" }; } /// /// 关卡详情预加载职业图标 /// public static void LevelDetailPreLoadJobIcon(bool isLoad) { List paths = new(); for (var i = Ejob.Job_Commander; i < Ejob.Job_Other; i++) { var path = GetJobIconPath(i); if (!paths.Contains(path)) paths.Add(path); } foreach (var iconPath in paths) { if (isLoad) AssetManager.Instance.PostPreload(iconPath).Forget(); else AssetManager.Instance.Unload(iconPath); } } public static void PreLoadLevelGroupBg(bool isLoad) { var levelGroups = TableManager.Instance.Tables.Chapter.DataList; List paths = new(); foreach (var levelGroup in levelGroups) { var path = levelGroup.MaterialIcon; if (!paths.Contains(path)) paths.Add(path); } foreach (var iconPath in paths) { if (isLoad) AssetManager.Instance.PostPreload(iconPath).Forget(); else AssetManager.Instance.Unload(iconPath); } } /// /// 返回到主场景 /// public static async void HomeToMain() { ChangeUIScene(Constants.MAIN_SCENE_PATH); if (!UIManager.Instance.CheckWindowCreated(UINameConst.UI_MainPanel)) { await UIManager.Instance.LoadWindow(UINameConst.UI_MainPanel); UIManager.Instance.CloseAllNormalExcept(UINameConst.UI_MainPanel); await UI_MainPanelController.Open(); } else UIManager.Instance.CloseAllNormalExcept(UINameConst.UI_MainPanel); } /// /// 返回到营地 /// /// public static void HomeToCamp() { ChangeUIScene(Constants.CAMP_SCENE_PATH); UIManager.Instance.CloseAllNormalExcept(UINameConst.UI_Camp); } public static Vector2 VectorTrans(cfg.vector2 vector) { return new Vector2(vector.X, vector.Y); } public static Vector3 VectorTrans(cfg.vector3 vector) { return new Vector3(vector.X, vector.Y, vector.Z); } public static Vector4 VectorTrans(cfg.vector4 vector) { return new Vector4(vector.X, vector.Y, vector.Z, vector.W); } } }