using System.Collections.Generic; using Framework; using Gameplay.Effect; using PhxhSDK; using UnityEngine; namespace Gameplay.Emoji { public class UnitEmojiManager { // public readonly Character.Character character; public GameObject rootObj; private Material _matBg; private Material _matUp; private Material _matMid; private Material _matDown; private string _oldImgPathBg; private string _oldImgPathUp; private string _oldImgPathMid; private string _oldImgPathDown; private List _emojiEffectIds; private List _effectDatas; private Color _eyeColor; private string _bowType; private static readonly int MainColor = Shader.PropertyToID("_MainColor"); // 暂时在这里写死,目前商量下来应该不会变动 private static string[] EMOJI_MASK_IDS = new string[] { "12", "13", "14", "15" }; private static readonly int MaskTex = Shader.PropertyToID("_MaskTex"); private Skeleton _skeleton; internal UnitEmojiManager(GameObject obj, string eyeColor, string bowType) { rootObj = obj; _eyeColor = ColorUtility.TryParseHtmlString(eyeColor, out var color) ? color : Color.white; _bowType = bowType; var collector = new ComponentCollector(obj); _skeleton = new Skeleton(collector.Transforms); _BindObj(); } private void _BindObj() { var emojiObj = _skeleton.GetBone("F_emoji"); if (emojiObj != null) { // 删除 Object.Destroy(emojiObj.gameObject); } var newEmojiObj = _skeleton.GetBone("G_emoji"); if (newEmojiObj == null) { DebugUtil.LogError("找不到表情的骨骼:G_emoji"); return; } rootObj = newEmojiObj.gameObject; var meshRender = rootObj.GetComponentInChildren(); // 这里直接去Inst的 var mats = meshRender.sharedMaterials; if (mats.Length != 4) { DebugUtil.LogError("表情的材质球数量不对"); return; } _matUp = Object.Instantiate(mats[0]); _matMid = Object.Instantiate(mats[1]); _matDown = Object.Instantiate(mats[2]); _matBg = Object.Instantiate(mats[3]); meshRender.materials = new Material[] { _matUp, _matMid, _matDown, _matBg }; _emojiEffectIds = new List(); _effectDatas = new List(); } public void Show() { if (rootObj.activeSelf) return; rootObj.SetActive(true); } public void Hide() { if (!rootObj.activeSelf) return; rootObj.SetActive(false); } private bool _CheckIsEmpty(string imgName) { if (string.IsNullOrEmpty(imgName)) return true; if (imgName == "0") return true; if (!int.TryParse(imgName, out var result)) { return true; } if (result == 0) { return true; } return false; } private string _GetFixNum(string imgName) { if (imgName.Length < 2) { return "0" + imgName; } return imgName; } private bool _WithMask(string imgName) { for (int i = 0; i < EMOJI_MASK_IDS.Length; i++) { var maskId = EMOJI_MASK_IDS[i]; if (imgName == maskId) return true; } return false; } public async void SwitchEmoji(int emojiId) { if (_matUp == null) return; if (emojiId == 0) return; #if UNITY_EDITOR var emojiCfg = EditorTableManager.instance.tables.EmojiConfig.Get(emojiId); #else var emojiCfg = TableManager.Instance.Tables.EmojiConfig.Get(emojiId); #endif if (emojiCfg == null) { DebugUtil.LogError("无效的emojiId:{0}", emojiId); return; } // 眉毛 T_emoji_eyebows_1_01 // 眼睛 T_emoji_eyes_01 // 嘴巴 T_emoji_mouth_01 // 背景 T_emoji_acc_01 const string emptyPath = "T_emoji_empty"; const string prefix = "Assets/Art/Character/Models/Emoji/Tex/"; var imgPathBg = _CheckIsEmpty(emojiCfg.BgImg) ? emptyPath : $"T_emoji_acc_{_GetFixNum(emojiCfg.BgImg)}"; var imgPathUp = _CheckIsEmpty(emojiCfg.UpImg) ? emptyPath : $"T_emoji_eyebows_{_bowType}_{_GetFixNum(emojiCfg.UpImg)}"; var imgPathMid = _CheckIsEmpty(emojiCfg.MidImg) ? emptyPath : $"T_emoji_eyes_{_GetFixNum(emojiCfg.MidImg)}"; var imgPathDown = _CheckIsEmpty(emojiCfg.DownImg) ? emptyPath : $"T_emoji_mouth_{_GetFixNum(emojiCfg.DownImg)}"; var maskPath = emptyPath; var isWithMask = _WithMask(emojiCfg.MidImg); if (isWithMask) { maskPath = imgPathMid + "_mask"; } imgPathBg = prefix + imgPathBg + ".png"; imgPathUp = prefix + imgPathUp + ".png"; imgPathMid = prefix + imgPathMid + ".png"; imgPathDown = prefix + imgPathDown + ".png"; maskPath = prefix + maskPath + ".png"; if (_oldImgPathBg != imgPathBg) { _oldImgPathBg = imgPathBg; _matBg.mainTexture = await AssetManager.Instance.LoadAssetAsync(imgPathBg); } if (_oldImgPathUp != imgPathUp) { _oldImgPathUp = imgPathUp; _matUp.mainTexture = await AssetManager.Instance.LoadAssetAsync(imgPathUp); } if (_oldImgPathMid != imgPathMid) { _oldImgPathMid = imgPathMid; if (isWithMask) { var maskTex = await AssetManager.Instance.LoadAssetAsync(maskPath); _matMid.SetTexture(MaskTex, maskTex); } else { _matMid.SetTexture(MaskTex, null); } _matMid.mainTexture = await AssetManager.Instance.LoadAssetAsync(imgPathMid); _matMid.SetColor(MainColor, _eyeColor); } if (_oldImgPathDown != imgPathDown) { _oldImgPathDown = imgPathDown; _matDown.mainTexture = await AssetManager.Instance.LoadAssetAsync(imgPathDown); } // 特效的判定 var effectIds = emojiCfg.EffectIds; var isSame = _CheckSame(effectIds, _emojiEffectIds); if (!isSame) { // 销毁旧的 for (var i = 0; i < _effectDatas.Count; ++i) { var effectData = _effectDatas[i]; effectData.Destroy(); } _effectDatas.Clear(); _emojiEffectIds = effectIds; if (Application.isPlaying) { // 获取特效 for (var i = 0; i < _emojiEffectIds.Count; ++i) { var effectId = _emojiEffectIds[i]; var effectData = EffectManager.instance.PlayEffectById(effectId, rootObj.transform.position, rootObj.transform.rotation, rootObj.transform); _effectDatas.Add(effectData); } } } Show(); } private static bool _CheckSame(IReadOnlyList a, IReadOnlyList b) { if (a.Count != b.Count) return false; for (var i = 0; i < a.Count; ++i) { if (a[i] != b[i]) return false; } return true; } } }