using UnityEngine; using Live2D.Cubism.Rendering; using System.IO; using FairyGUI; using UnityEngine.Rendering; namespace GFGGame { public class DressUpUtil { private const string HEAD_DEFAULT_RES_NAME = "head"; private const string BODY_DEFAULT_RES_NAME = "body"; private const string ROLE_OBJ_NAME = "Role"; private const string HEAD_SPRITE_NAME = "Head"; private const string BODY_SPRITE_NAME = "Body"; public const string BODY_ANIMATION_NAME = "Body_a"; private const string BODY_EFFECT_OBJ_NAME = "Body_eff"; public const string FORMAT_SPRITE_NAME = "T{0}_s{1}"; private const string FORMAT_ANIMATION_NAME = "T{0}_a{1}"; private const string FORMAT_EFFECT_OBJ_NAME = "T{0}_e{1}"; public static void AddItem(int itemID, GameObject sceneObj, bool needSetMask = false, bool showAni = true, GameObject parentObj = null, int resLayer = 0) { ItemCfg itemCfg = ItemCfgArray.Instance.GetCfg(itemID); if (itemCfg != null) { // GameObject parentObj = null; if (parentObj == null) { if (itemCfg.subType == ConstDressUpItemType.BEI_JING || DressUpMenuItemCfg1Array.Instance.CheckIsSceneTypeBySubType(itemCfg.subType)) { parentObj = sceneObj; } else { //角色 Transform role = sceneObj.transform.Find(ROLE_OBJ_NAME); parentObj = role.gameObject; } } showAni = showAni || itemCfg.subType == ConstDressUpItemType.ZHUANG_RONG; if (resLayer > 0) { string layerName = ""; switch (resLayer) { case 1: layerName = itemCfg.resLayer1; break; case 2: layerName = itemCfg.resLayer2; break; case 3: layerName = itemCfg.resLayer3; break; } if (!string.IsNullOrEmpty(layerName)) { updateLayerRes(itemCfg, parentObj, resLayer, needSetMask, showAni); } // updateLayerRes(itemCfg, parentObj, resLayer, resLayer == 2, needSetMask, showAni); } else { //普通层 if (!string.IsNullOrEmpty(itemCfg.resLayer1)) { updateLayerRes(itemCfg, parentObj, 1, needSetMask, showAni); } //第二层 if (!string.IsNullOrEmpty(itemCfg.resLayer2)) { updateLayerRes(itemCfg, parentObj, 2, needSetMask, showAni); } //第三层 if (!string.IsNullOrEmpty(itemCfg.resLayer3)) { updateLayerRes(itemCfg, parentObj, 3, needSetMask, showAni); } } } } public static void RemoveItem(int itemID, GameObject sceneObj, GameObject parentObj = null) { ItemCfg itemCfg = ItemCfgArray.Instance.GetCfg(itemID); if (itemCfg != null) { if (parentObj == null) { if (itemCfg.subType == ConstDressUpItemType.BEI_JING || DressUpMenuItemCfg1Array.Instance.CheckIsSceneTypeBySubType(itemCfg.subType)) { parentObj = sceneObj; } else { //角色 Transform role = sceneObj.transform.Find(ROLE_OBJ_NAME); parentObj = role.gameObject; } } string spritObjName; string aniObjName; //默认层 if (!string.IsNullOrEmpty(itemCfg.resLayer1)) { spritObjName = string.Format(FORMAT_SPRITE_NAME, itemCfg.subType, 1); TryClearSpriteObj(parentObj, spritObjName); aniObjName = string.Format(FORMAT_ANIMATION_NAME, itemCfg.subType, 1); TryRemoveObj(parentObj, aniObjName); aniObjName = string.Format(FORMAT_EFFECT_OBJ_NAME, itemCfg.subType, 1); TryRemoveObj(parentObj, aniObjName); } //特殊层 if (!string.IsNullOrEmpty(itemCfg.resLayer2)) { spritObjName = string.Format(FORMAT_SPRITE_NAME, itemCfg.subType, 2); TryClearSpriteObj(parentObj, spritObjName); aniObjName = string.Format(FORMAT_ANIMATION_NAME, itemCfg.subType, 2); TryRemoveObj(parentObj, aniObjName); aniObjName = string.Format(FORMAT_EFFECT_OBJ_NAME, itemCfg.subType, 2); TryRemoveObj(parentObj, aniObjName); } //第三层 if (!string.IsNullOrEmpty(itemCfg.resLayer3)) { spritObjName = string.Format(FORMAT_SPRITE_NAME, itemCfg.subType, 3); TryClearSpriteObj(parentObj, spritObjName); aniObjName = string.Format(FORMAT_ANIMATION_NAME, itemCfg.subType, 3); TryRemoveObj(parentObj, aniObjName); aniObjName = string.Format(FORMAT_EFFECT_OBJ_NAME, itemCfg.subType, 3); TryRemoveObj(parentObj, aniObjName); } } } public static void InitHead(GameObject sceneObj, bool needSetMask = false, GameObject parentObj = null) { var roleTf = sceneObj.transform.Find(ROLE_OBJ_NAME); parentObj = parentObj == null ? roleTf.gameObject : parentObj; string res = HEAD_DEFAULT_RES_NAME; Transform transform_t = parentObj.transform.Find(HEAD_SPRITE_NAME); if (transform_t != null) { return; } AddSpriteObj(res, "png", HEAD_SPRITE_NAME, parentObj, 1, needSetMask); } public static void UpdateWholeBody(string res, GameObject sceneObj, bool isAni = false, string effRes = null, bool needSetMask = false, GameObject parentObj = null) { InitHead(sceneObj, needSetMask, parentObj); UpdateBodyOnly(res, sceneObj, isAni, effRes, needSetMask, parentObj); } public static void UpdateBodyOnly(string res, GameObject sceneObj, bool isAni = false, string effRes = null, bool needSetMask = false, GameObject parentObj = null) { //角色 var roleTf = sceneObj.transform.Find(ROLE_OBJ_NAME); parentObj = parentObj == null ? roleTf.gameObject : parentObj; if (res == null) { res = BODY_DEFAULT_RES_NAME; } //清理旧的 TryClearSpriteObj(parentObj, BODY_SPRITE_NAME); var removeBodyAni = TryRemoveObj(parentObj, BODY_ANIMATION_NAME); TryRemoveObj(parentObj, BODY_EFFECT_OBJ_NAME); if (isAni) { AddAnimationObj(res, BODY_ANIMATION_NAME, parentObj, 0); } else { AddSpriteObj(res, "png", BODY_SPRITE_NAME, parentObj, 0, needSetMask); if (removeBodyAni) { parentObj.transform.SetPositionAndRotation(new Vector3(), new Quaternion()); } } //特效 if (!string.IsNullOrEmpty(effRes)) { TryAddEffectObj(effRes, BODY_EFFECT_OBJ_NAME, parentObj, 0); } } public static void AddAssetReleaser(GameObject gameObj, string resPath) { var assetDisposer = gameObj.AddComponent(); assetDisposer.resPath = resPath; } public static void ChangeAssetReleaser(GameObject gameObj, string resPath) { var assetDisposer = gameObj.GetComponent(); if (assetDisposer == null) { assetDisposer = gameObj.AddComponent(); } assetDisposer.resPath = resPath; } private static void updateLayerRes(ItemCfg itemCfg, GameObject parentObj, int layerId, bool needSetMask, bool showAni = true) { ItemTypeCfg typeCfg = ItemTypeCfgArray.Instance.GetCfg(itemCfg.subType); string res = itemCfg.res; int sortingOrder = typeCfg.defaultLayer; switch (layerId) { case 1: res = itemCfg.resLayer1 == "n" ? res : string.Format("{0}_{1}", res, itemCfg.resLayer1); break; case 2: sortingOrder = typeCfg.specialLayer; res = itemCfg.resLayer2 == "n" ? res : string.Format("{0}_{1}", res, itemCfg.resLayer2); break; case 3: sortingOrder = typeCfg.thirdlLayer; res = itemCfg.resLayer3 == "n" ? res : string.Format("{0}_{1}", res, itemCfg.resLayer3); break; } //清理旧的 var spritObjName = string.Format(FORMAT_SPRITE_NAME, itemCfg.subType, layerId); TryClearSpriteObj(parentObj, spritObjName); var aniObjName = string.Format(FORMAT_ANIMATION_NAME, itemCfg.subType, layerId); TryRemoveObj(parentObj, aniObjName); string ext = ItemUtil.GetItemResExt(itemCfg.itemType, itemCfg.subType); //这里需要先添加静态图,防止加载动画有延迟,出现光头 GameObject spriteObj = AddSpriteObj(res, ext, spritObjName, parentObj, sortingOrder, needSetMask); if (showAni) { var aniObj = AddAnimationObj(res, aniObjName, parentObj, sortingOrder); if (aniObj != null && spriteObj != null) { Timers.inst.Add(0.03f, 1, (obj) => { if (parentObj != null && parentObj.transform != null) { Transform tf = parentObj.transform.Find(spritObjName); if (tf != null && tf.gameObject != null && tf.gameObject.activeInHierarchy) { var assetDisposer = tf.gameObject.GetComponent(); if (assetDisposer != null) { if (!string.IsNullOrEmpty(assetDisposer.resPath)) { string resPath = ResPathUtil.GetDressUpPath(res, ext); if (assetDisposer.resPath == resPath) { TryClearSpriteObj(parentObj, spritObjName); } } } } } }); } } aniObjName = string.Format(FORMAT_EFFECT_OBJ_NAME, itemCfg.subType, layerId); TryRemoveObj(parentObj, aniObjName); TryAddEffectObj(res, aniObjName, parentObj, sortingOrder); } private static GameObject AddSpriteObj(string res, string ext, string objName, GameObject parentObj, int sortingOrder, bool needSetMask) { string resPath = ResPathUtil.GetDressUpPath(res, ext); if (!VEngine.Versions.Contains(resPath)) { return null; } SpriteRenderer spr = null; var gameObj = parentObj.transform.Find(objName)?.gameObject; if (gameObj == null) { gameObj = new GameObject(objName); gameObj.transform.SetParent(parentObj.transform, false); AddAssetReleaser(gameObj, resPath); } spr = gameObj.GetComponent(); if (spr == null) { spr = gameObj.AddComponent(); } float tx, ty; LoadSpritePos(res, out tx, out ty); gameObj.transform.localPosition = new Vector3(tx, ty, gameObj.transform.localPosition.z); Sprite sp = GFGAsset.Load(resPath); spr.sprite = sp; spr.sortingOrder = sortingOrder; if (needSetMask) { spr.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; if (parentObj.transform.parent != null && parentObj.transform.parent.name == "targetRole") { spr.maskInteraction = SpriteMaskInteraction.VisibleOutsideMask; } else { spr.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; } } else { spr.maskInteraction = SpriteMaskInteraction.None; } return gameObj; } public static void TryClearSpriteObj(GameObject parentObj, string spritObjName) { if (parentObj == null) { return; } Transform transform_t = parentObj.transform.Find(spritObjName); if (transform_t != null) { GameObject gameObj_t = transform_t.gameObject; if (gameObj_t != null) { //SpriteRenderer spr = null; //spr = gameObj_t.GetComponent(); //if(spr != null) //{ // spr.sprite = null; //} // var assetDisposer = gameObj_t.GetComponent(); // if (assetDisposer != null) // { // if (!string.IsNullOrEmpty(assetDisposer.resPath)) // { // GFGAsset.Release(assetDisposer.resPath); // assetDisposer.resPath = null; // } // } // SpriteRenderer spr = gameObj_t.GetComponent(); // if (spr != null) // { // GameObject.Destroy(spr); // } GameObject.DestroyImmediate(gameObj_t); } } } private static GameObject AddAnimationObj(string res, string objName, GameObject parentObj, int sortingOrder) { string resPath = ResPathUtil.GetDressUpAnimationPath(res); if (!VEngine.Versions.Contains(resPath)) { return null; } var prefab = GFGAsset.Load(resPath); var gameObj = GameObject.Instantiate(prefab); AddAssetReleaser(gameObj, resPath); if (objName == BODY_ANIMATION_NAME) { //如果是动作动画,就根据动画位置及角度信息设置给Role对象 parentObj.transform.SetPositionAndRotation(gameObj.transform.localPosition, gameObj.transform.localRotation); gameObj.transform.SetPositionAndRotation(new Vector3(), new Quaternion()); } gameObj.name = objName; gameObj.transform.SetParent(parentObj.transform, false); var render = gameObj.GetComponent(); if (render == null && gameObj.transform.childCount > 0) { var childObj = gameObj.transform.GetChild(0); if (childObj != null) { render = childObj.GetComponent(); } } if (render != null && render.gameObject.activeSelf == true) { render.SortingOrder = sortingOrder; } SetParticleSortingOrder(gameObj, sortingOrder); return gameObj; } private static bool TryRemoveObj(GameObject parentObj, string aniObjName) { if (parentObj == null) { return false; } Transform transform = parentObj.transform.Find(aniObjName); if (transform != null) { GameObject gameObj = transform.gameObject; if (gameObj != null) { GameObject.DestroyImmediate(gameObj); return true; } } return false; } public static GameObject CreateAnimationObj(string resPath) { // string resPath = ResPathUtil.GetCardAnimationPath(res); var prefab = GFGAsset.Load(resPath); if (prefab == null) { return null; } var gameObj = GameObject.Instantiate(prefab); AddAssetReleaser(gameObj, resPath); return gameObj; } private static void TryAddEffectObj(string res, string objName, GameObject parentObj, int sortingOrder) { var resPath = ResPathUtil.GetDressUpEffectPath(res); if (!VEngine.Versions.Contains(resPath)) { return; } GameObject effPre = GFGAsset.Load(resPath); var gameObj = GameObject.Instantiate(effPre); AddAssetReleaser(gameObj, resPath); gameObj.transform.SetParent(parentObj.transform, false); gameObj.name = objName; var sortingGroup = gameObj.transform.GetComponent(); if (sortingGroup == null) { sortingGroup = gameObj.AddComponent(); } sortingGroup.sortingOrder = sortingOrder + 1;//特效层默认高一个层级 //SetParticleSortingOrder(gameObj, sortingOrder + 1);//特效层默认高一个层级 } public static void LoadSpritePos(string res, out float tx, out float ty) { string resPath = ResPathUtil.GetDressUpPath(res, "bytes"); if (VEngine.Versions.Contains(resPath)) { var asset = GFGAsset.Load(resPath); if (asset != null) { var st = new MemoryStream(asset.bytes); var br = new BinaryReader(st); tx = br.ReadInt32() / 100f; ty = -br.ReadInt32() / 100f; GFGAsset.Release(resPath); return; } } tx = 0; ty = 0; } public static void SetParticleSortingOrder(GameObject gameObj, int sortingOrder, bool isAdd = false) { ParticleSystem[] particles = gameObj.transform.GetComponentsInChildren(); for (int i = 0; i < particles.Length; i++) { var renderer = particles[i].GetComponent(); if (renderer != null) { if (isAdd) { renderer.sortingOrder = renderer.sortingOrder + sortingOrder; } else { renderer.sortingOrder = sortingOrder; } } } } public static void SetSpriteRenderSortingOrder(GameObject gameObj, int sortingOrder, bool isAdd = false) { SpriteRenderer[] spriteRenders = gameObj.transform.GetComponentsInChildren(); for (int i = 0; i < spriteRenders.Length; i++) { if (isAdd) { spriteRenders[i].sortingOrder = spriteRenders[i].sortingOrder + sortingOrder; } else { spriteRenders[i].sortingOrder = sortingOrder; } } } } }