| | |
| | | /// <param name="autoDestroy">是否自动销毁,默认为true</param> |
| | | /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param> |
| | | /// <returns>特效游戏对象</returns> |
| | | public GameObject PlayUIEffect(int id, Transform parent = null, bool autoDestroy = true, float destroyDelay = 5f) |
| | | public EffectPlayer PlayUIEffect(int id, Transform parent = null, bool autoDestroy = true, float destroyDelay = 5f) |
| | | { |
| | | // 使用默认值 |
| | | if (parent == null) parent = transform; |
| | | |
| | | EffectConfig effectCfg = EffectConfig.Get(id); |
| | | EffectPlayer player = parent.gameObject.AddComponent<EffectPlayer>(); |
| | | |
| | | if (null == effectCfg) |
| | | { |
| | | return null; |
| | | } |
| | | player.effectId = id; |
| | | player.autoDestroy = autoDestroy; |
| | | player.destroyDelay = destroyDelay; |
| | | player.canvas = canvas; |
| | | |
| | | // 加载特效资源 |
| | | var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectCfg.packageName, effectCfg.fxName); |
| | | if (effectPrefab == null) |
| | | { |
| | | Debug.LogError($"加载UI特效失败: {effectCfg.packageName}"); |
| | | return null; |
| | | } |
| | | |
| | | // 实例化特效 |
| | | GameObject effectObj = Instantiate(effectPrefab, parent); |
| | | effectObj.name = $"Effect_{effectCfg.packageName}"; |
| | | |
| | | // 添加特效穿透阻挡器 |
| | | EffectPenetrationBlocker blocker = effectObj.AddComponent<EffectPenetrationBlocker>(); |
| | | blocker.parentCanvas = canvas; |
| | | |
| | | // 延迟一帧才生效 |
| | | this.DelayFrame(blocker.UpdateSortingOrder); |
| | | |
| | | // blocker.UpdateSortingOrder(); |
| | | |
| | | // 自动销毁 |
| | | if (autoDestroy) |
| | | { |
| | | Destroy(effectObj, destroyDelay); |
| | | } |
| | | |
| | | return effectObj; |
| | | return player; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 在两个UI元素之间播放特效(按照sortingOrder的中间值) |
| | | /// </summary> |
| | | /// <param name="effectName">特效资源名称</param> |
| | | /// <param name="frontElement">前景UI元素(Image或RawImage)</param> |
| | | /// <param name="backElement">背景UI元素(Image或RawImage)</param> |
| | | /// <param name="autoDestroy">是否自动销毁,默认为true</param> |
| | | /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param> |
| | | /// <returns>特效游戏对象</returns> |
| | | public async UniTask<GameObject> PlayEffectBetweenUIElements(string effectName, Graphic frontElement, Graphic backElement, bool autoDestroy = true, float destroyDelay = 5f) |
| | | { |
| | | if (frontElement == null || backElement == null) |
| | | { |
| | | Debug.LogError("前景或背景UI元素为空"); |
| | | return null; |
| | | } |
| | | |
| | | // 确保UI元素在当前UIBase的Canvas下 |
| | | if (frontElement.canvas != canvas || backElement.canvas != canvas) |
| | | { |
| | | Debug.LogError("UI元素不在当前UIBase的Canvas下"); |
| | | return null; |
| | | } |
| | | |
| | | // 加载特效资源 |
| | | GameObject effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName); |
| | | if (effectPrefab == null) |
| | | { |
| | | Debug.LogError($"加载UI特效失败: {effectName}"); |
| | | return null; |
| | | } |
| | | |
| | | // 创建一个新的GameObject作为特效容器 |
| | | GameObject container = new GameObject($"EffectContainer_{effectName}"); |
| | | container.transform.SetParent(transform, false); |
| | | |
| | | // 设置容器位置 |
| | | RectTransform containerRect = container.AddComponent<RectTransform>(); |
| | | containerRect.anchorMin = new Vector2(0.5f, 0.5f); |
| | | containerRect.anchorMax = new Vector2(0.5f, 0.5f); |
| | | containerRect.pivot = new Vector2(0.5f, 0.5f); |
| | | containerRect.anchoredPosition = Vector2.zero; |
| | | containerRect.sizeDelta = new Vector2(100, 100); // 默认大小,可以根据需要调整 |
| | | |
| | | // 获取前景和背景元素的siblingIndex |
| | | int frontIndex = frontElement.transform.GetSiblingIndex(); |
| | | int backIndex = backElement.transform.GetSiblingIndex(); |
| | | |
| | | // 设置特效容器的siblingIndex在两者之间 |
| | | if (frontIndex > backIndex) |
| | | { |
| | | // 前景在背景之后,特效应该在中间 |
| | | container.transform.SetSiblingIndex((frontIndex + backIndex) / 2 + 1); |
| | | } |
| | | else |
| | | { |
| | | // 背景在前景之后,特效应该在中间 |
| | | container.transform.SetSiblingIndex((frontIndex + backIndex) / 2); |
| | | } |
| | | |
| | | // 实例化特效 |
| | | GameObject effectObj = Instantiate(effectPrefab, container.transform); |
| | | effectObj.name = $"Effect_{effectName}"; |
| | | |
| | | // 添加特效穿透阻挡器 |
| | | EffectPenetrationBlocker blocker = effectObj.AddComponent<EffectPenetrationBlocker>(); |
| | | |
| | | // 直接设置特效渲染器的排序顺序 |
| | | Renderer[] renderers = effectObj.GetComponentsInChildren<Renderer>(true); |
| | | foreach (Renderer renderer in renderers) |
| | | { |
| | | renderer.sortingOrder = canvas.sortingOrder; |
| | | renderer.sortingLayerName = canvas.sortingLayerName; |
| | | } |
| | | |
| | | // 设置粒子系统渲染器的排序顺序 |
| | | ParticleSystem[] particleSystems = effectObj.GetComponentsInChildren<ParticleSystem>(true); |
| | | foreach (ParticleSystem ps in particleSystems) |
| | | { |
| | | ParticleSystemRenderer psRenderer = ps.GetComponent<ParticleSystemRenderer>(); |
| | | if (psRenderer != null) |
| | | { |
| | | psRenderer.sortingOrder = canvas.sortingOrder; |
| | | psRenderer.sortingLayerName = canvas.sortingLayerName; |
| | | } |
| | | } |
| | | |
| | | // 自动销毁 |
| | | if (autoDestroy) |
| | | { |
| | | Destroy(container, destroyDelay); |
| | | } |
| | | |
| | | return effectObj; |
| | | } |
| | | #endregion |
| | | |
| | | public bool raycastTarget |