unity实现截屏-全屏-区域截屏
·
放个美女养眼

注意事项
- 只测试Canvas是ScreenSpace-Camera模式的情况
- 需要Unitask插件
- 单例自己维护下,会报错
- 会自动保存成jpg到特定目录
代码速览
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;
}
}
一键三联
点赞·留言·收藏
如果可以帮到你,好用的话,记得一键三连。
毕竟博主写文章是靠爱发电,所以爱会消失对不对。


更多推荐
所有评论(0)