覆盖索引与超长分页优化
2026/10/15 4:07:48
public async UniTask<CaptureData> BeginCaptureByRect(RectTransform rtUI) public async UniTask<CaptureData> BeginCapture() ScreenCapture.Instance.BeginCapture(); ScreenCapture.Instance.BeginCaptureByRect();using System; using System.IO; using System.Threading.Tasks; using Cysharp.Threading.Tasks; using MiaoLeGeMi.Tool; using UnityEngine; using UnityEngine.UI; using static System.Net.Mime.MediaTypeNames; using static Unity.VisualScripting.Member; namespace MiaoLeGeMi { public class ScreenCapture : SingleMono<ScreenCapture> { [SerializeField] private CaptureData Data; [ContextMenu("测试截屏")] public async void Test() { CaptureData d = await BeginCapture(); Debug.Log(d.SavePath); } /// <summary> /// 返回保存目录 /// </summary> /// <param name="autoSave"></param> /// <returns></returns> public async UniTask<CaptureData> BeginCapture() { Debug.Log("开始截屏"); await UniTask.WaitForEndOfFrame(this); int width = Screen.width; int height = Screen.height; Texture2D t2d = new Texture2D(width, height, TextureFormat.RGB24, false); Rect rect = new Rect(0, 0, width, height); t2d.ReadPixels(rect, 0, 0); t2d.Apply(); Debug.Log("结束截屏"); string dir = GetDownloadDirectory(); string fileName = DateTime.Now.Ticks.ToString() + ".jpg"; string fullpath = Path.Combine(dir, fileName); byte[] data = t2d.EncodeToJPG(80); File.WriteAllBytes(fullpath, data); Debug.Log($"写入文件:{fullpath}"); CaptureData d = new CaptureData(); d.SavePath = fullpath; d.t2d = t2d; await UniTask.CompletedTask; return d; } public async UniTask<CaptureData> BeginCaptureByRect(RectTransform rtUI) { // 等待帧结束,确保布局已更新 await UniTask.WaitForEndOfFrame(this); Canvas canvas = rtUI.GetComponentInParent<Canvas>(); if (canvas == null) { Debug.LogError("RectTransform 不在 Canvas 下!"); return null; } // 获取 Canvas 的逻辑尺寸(即参考分辨率) RectTransform canvasRect = canvas.GetComponent<RectTransform>(); Vector2 canvasSize = canvasRect.rect.size; Debug.Log($"Canvas 尺寸: {canvasSize.x} x {canvasSize.y}"); // ---- 使用 anchoredPosition + sizeDelta 计算截取区域 ---- Vector2 centerOffset = rtUI.anchoredPosition; // 中心相对于父级(Canvas)中心的偏移 Vector2 size = rtUI.sizeDelta; // UI 元素的宽高(锚点居中的情况下等于实际尺寸) // 左下角相对于 Canvas 中心的偏移 float leftOffset = centerOffset.x - size.x * 0.5f; float bottomOffset = centerOffset.y - size.y * 0.5f; // 转换为以 Canvas 左下角为原点的像素坐标(与 RenderTexture 坐标一致) float x = leftOffset + canvasSize.x * 0.5f; float y = bottomOffset + canvasSize.y * 0.5f; float width = size.x; float height = size.y; // 边界裁剪(防止溢出) x = Mathf.Clamp(x, 0, canvasSize.x); y = Mathf.Clamp(y, 0, canvasSize.y); width = Mathf.Min(width, canvasSize.x - x); height = Mathf.Min(height, canvasSize.y - y); Debug.Log($"截取区域: x={x}, y={y}, w={width}, h={height}"); // ---- 创建 RenderTexture 并渲染 Canvas ---- int rtWidth = Mathf.RoundToInt(canvasSize.x); int rtHeight = Mathf.RoundToInt(canvasSize.y); RenderTexture rt = new RenderTexture(rtWidth, rtHeight, 16); Camera cam = canvas.worldCamera; if (cam == null) { Debug.LogError("Canvas 的 worldCamera 为空!"); return null; } RenderTexture prevRT = cam.targetTexture; cam.targetTexture = rt; cam.Render(); cam.targetTexture = prevRT; // ---- 从 RT 中截取指定区域 ---- RenderTexture.active = rt; Texture2D t2d = new Texture2D(Mathf.RoundToInt(width), Mathf.RoundToInt(height), TextureFormat.RGB24, false); t2d.ReadPixels(new Rect(x, y, width, height), 0, 0); t2d.Apply(); RenderTexture.active = null; // 释放 RenderTexture rt.Release(); DestroyImmediate(rt); // ---- 保存截图 ---- string dir = GetDownloadDirectory(); string fileName = DateTime.Now.Ticks.ToString() + ".jpg"; string fullpath = Path.Combine(dir, fileName); byte[] data = t2d.EncodeToJPG(80); File.WriteAllBytes(fullpath, data); Debug.Log($"写入文件:{fullpath}"); CaptureData d = new CaptureData { SavePath = fullpath, t2d = t2d }; await UniTask.CompletedTask; return d; } private static string GetDownloadDirectory() { // Application.dataPath 在编辑器下指向 Assets,打包后指向 Data 文件夹 string rootDir = Directory.GetParent(UnityEngine.Application.dataPath).FullName; // 项目根目录 或 exe 所在目录 string dirName = "UserCaches"; string targetDir = Path.Combine(rootDir, dirName); if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir); return targetDir; } } [Serializable] public class CaptureData { public string SavePath; public Texture2D t2d; } }点赞·留言·收藏
如果可以帮到你,好用的话,记得一键三连。
毕竟博主写文章是靠爱发电,所以爱会消失对不对。