using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; using System.IO; public class MultiImageBlender : MonoBehaviour { [Header("Base Settings")] public RectTransform container; public Shader blendShader; public string fileName = "MultiBlendResult"; public string saveFolder = "Exports"; [Header("Advanced Settings")] [Tooltip("Render order: from bottom to top (child index)")] public bool useHierarchyOrder = true; public Vector2Int outputResolution = new Vector2Int(1024, 1024); private List targetImages = new List(); private RenderTexture compositeRT; [ContextMenu("Execute Blend Export")] public void ExecuteBlendExport() { // 初始化目标列表 CollectImages(); // 创建渲染目标 CreateRenderTexture(); // 初始化画布 ClearRenderTexture(compositeRT, Color.clear); // 混合所有图片 foreach (Image img in targetImages) { if (!img.gameObject.activeInHierarchy) continue; if (img.sprite == null) { continue; } // 准备纹理数据 Texture2D coloredTex = ProcessImageTexture(img); Vector2 offset = CalculatePositionOffset(img.rectTransform); // 执行混合 BlendLayer(coloredTex, img.color, offset); DestroyImmediate(coloredTex); } // 保存结果 SaveResult(); // 清理资源 ReleaseResources(); } void CollectImages() { targetImages.Clear(); if (useHierarchyOrder) { // 按层级顺序收集(从底到顶) foreach (Transform child in container) { CollectRecursive(child); } } else { // 使用无序模式 Image[] images = container.GetComponentsInChildren(); targetImages.AddRange(images); } void CollectRecursive(Transform parent) { Image img = parent.GetComponent(); if (img != null) targetImages.Add(img); foreach (Transform child in parent) { CollectRecursive(child); } } } Texture2D ProcessImageTexture(Image image) { // 获取原始纹理 Texture2D sourceTex = image.sprite.texture; // 应用颜色 Color[] pixels = sourceTex.GetPixels(); for (int i = 0; i < pixels.Length; i++) { pixels[i] = pixels[i] * image.color; } // 创建新纹理 Texture2D coloredTex = new Texture2D( sourceTex.width, sourceTex.height, sourceTex.format, false ); coloredTex.SetPixels(pixels); coloredTex.Apply(); return coloredTex; } Vector2 CalculatePositionOffset(RectTransform rt) { // 将局部坐标转换为容器空间坐标 Vector2 anchoredPos = rt.anchoredPosition; // 计算标准化偏移(相对于输出分辨率) return new Vector2( anchoredPos.x / outputResolution.x, anchoredPos.y / outputResolution.y ); } void CreateRenderTexture() { if (compositeRT != null) compositeRT.Release(); compositeRT = new RenderTexture( outputResolution.x, outputResolution.y, 24, RenderTextureFormat.ARGB32 ); } void ClearRenderTexture(RenderTexture rt, Color clearColor) { RenderTexture.active = rt; GL.Clear(true, true, clearColor); RenderTexture.active = null; } void BlendLayer(Texture2D sourceTex, Color blendColor, Vector2 offset) { Material blendMat = new Material(blendShader); blendMat.SetTexture("_MainTex", sourceTex); blendMat.SetColor("_BlendColor", blendColor); blendMat.SetVector("_BlendOffset", offset); // 临时RT用于混合 RenderTexture tempRT = RenderTexture.GetTemporary( compositeRT.width, compositeRT.height, 0, compositeRT.format ); // 复制当前状态 Graphics.Blit(compositeRT, tempRT); // 执行混合 Graphics.Blit(tempRT, compositeRT, blendMat); // 清理临时RT RenderTexture.ReleaseTemporary(tempRT); DestroyImmediate(blendMat); } void SaveResult() { Texture2D outputTex = new Texture2D( compositeRT.width, compositeRT.height, TextureFormat.ARGB32, false ); RenderTexture.active = compositeRT; outputTex.ReadPixels(new Rect(0, 0, compositeRT.width, compositeRT.height), 0, 0); outputTex.Apply(); // 保存文件 string dirPath = Path.Combine(Application.dataPath, saveFolder); Directory.CreateDirectory(dirPath); string filePath = Path.Combine(dirPath, fileName + ".png"); File.WriteAllBytes(filePath, outputTex.EncodeToPNG()); Debug.Log($"导出成功:{filePath}"); DestroyImmediate(outputTex); } void ReleaseResources() { if (compositeRT != null) { compositeRT.Release(); DestroyImmediate(compositeRT); } Resources.UnloadUnusedAssets(); } void OnDestroy() { ReleaseResources(); } }