Unity仿照QQ截图,且在热更新环境下可用。

文章介绍了在Unity3D中,一个原本用于截图的脚本在热更新场景下遇到问题,作者经过测试和修改解决了这个问题。修复后的脚本能正确截取并保存游戏屏幕区域的图像,同时提供了选择保存路径的功能。修复主要涉及截取像素数据、创建新纹理以及保存到本地的过程。
摘要由CSDN通过智能技术生成

由于之前的截图脚本无法在热更新场景下使用,非常无奈,多方测试才解决问题。
预制体构造图请添加图片描述
请添加图片描述
请添加图片描述

原脚本,不用热更新可以使用,我忘了是哪位大佬写的,非原创感谢那位大佬

using UnityEngine;
using System.Collections;
using System.IO;
using System;
using System.Runtime.InteropServices;


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
    public int structSize = 0;
    public IntPtr dlgOwner = IntPtr.Zero;
    public IntPtr instance = IntPtr.Zero;
    public String filter = null;
    public String customFilter = null;
    public int maxCustFilter = 0;
    public int filterIndex = 0;
    public String file = null;
    public int maxFile = 0;
    public String fileTitle = null;
    public int maxFileTitle = 0;
    public String initialDir = null;
    public String title = null;
    public int flags = 0;
    public short fileOffset = 0;
    public short fileExtension = 0;
    public String defExt = null;
    public IntPtr custData = IntPtr.Zero;
    public IntPtr hook = IntPtr.Zero;
    public String templateName = null;
    public IntPtr reservedPtr = IntPtr.Zero;
    public int reservedInt = 0;
    public int flagsEx = 0;
}
public class SelectFileDialog
{
    //指定系统函数  
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
    public static bool GetSFN([In, Out] OpenFileName ofn)
    {
        return GetSaveFileName(ofn);
    }
}
public class CutUI : MonoBehaviour
{
    Vector2 StartPos,TempPos;  //画布内位置
    Vector3 StMsPos, EdMsPos;  //屏幕内位置
    public RectTransform SelImg;
    private RectTransform Canvas;
    public GameObject CutBtns,StartCut;

    bool isCutting = false, isPressed = false;

    private void Start()
    {
        CutBtns.SetActive(false);
        SelImg.gameObject.SetActive(false);
        Canvas = GameObject.Find("Canvas").GetComponent<RectTransform>();
    }

    // Update is called once per frame
    void Update()
    {
        if (isCutting && Input.GetMouseButtonDown(0))
        {
            isPressed = true;
            CutBtns.SetActive(false);
            SelImg.gameObject.SetActive(true);
            StMsPos = Input.mousePosition;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(Canvas, StMsPos, null, out StartPos);
            SelImg.anchoredPosition = StartPos;
        }
        if (isCutting && Input.GetMouseButton(0))
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(Canvas, Input.mousePosition, null, out TempPos);
            SelImg.pivot = new Vector2(TempPos.x >= StartPos.x ? 0 : 1, TempPos.y >= StartPos.y ? 0 : 1);
            SelImg.sizeDelta = new Vector2(Mathf.Abs(TempPos.x - StartPos.x), Mathf.Abs(TempPos.y - StartPos.y));
        }
        if (isCutting && isPressed  && Input.GetMouseButtonUp(0))
        {
            isPressed = false;
            isCutting = false;
            EdMsPos = Input.mousePosition;
            CutBtns.SetActive(true);
        }
    }
    
    Rect CutRect;
    private Texture2D Tex;
    IEnumerator CutImage()
    {
        string Name = DateTime.Now.ToString("yyyyMMddHHmmss");

        Tex = new Texture2D((int)Mathf.Abs(StMsPos.x - EdMsPos.x), (int)Mathf.Abs(StMsPos.y - EdMsPos.y), TextureFormat.RGB24, true);

        CutRect = new Rect(StMsPos.x> EdMsPos.x? EdMsPos.x: StMsPos.x,
           StMsPos.y > EdMsPos.y ? EdMsPos.y : StMsPos.y,
           Mathf.Abs(EdMsPos.x - StMsPos.x), 
           Mathf.Abs(EdMsPos.y - StMsPos.y));

        yield return new WaitForEndOfFrame();
        Tex.ReadPixels(CutRect, 0, 0, true);
        Tex.Apply();
        yield return Tex;
        byte[] bytes = Tex.EncodeToPNG();

        string path = Application.dataPath + "/" + Name + ".png";

        OpenFileName file = new OpenFileName();
        file.structSize = Marshal.SizeOf(file);
        file.filter = "文件(*.png)";
        file.file = new string(new char[256]);
        file.maxFile = file.file.Length;
        file.fileTitle = new string(new char[64]);
        file.maxFileTitle = file.fileTitle.Length;
        file.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
        file.title = "保存文件";
        file.templateName = Name;
        file.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;

        if (SelectFileDialog.GetSaveFileName(file))
        {
            path = file.file + ".png";
        }
        File.WriteAllBytes(path, bytes);
    }

    public void ClickCut() {
        CutBtns.SetActive(false);
        SelImg.gameObject.SetActive(false);
        StartCoroutine(CutImage());
        StartCut.SetActive(true);
    }

    public void ClickCancel()
    {
        CutBtns.SetActive(false);
        SelImg.gameObject.SetActive(false);
        StartCut.SetActive(true);
    }

    public void ClickStartCut() {
       
        isCutting = true;
    }
}

阿里云盘:https://www.aliyundrive.com/s/qCFon9eLtTD

后热更新修改后脚本,预制体没有改变

using UnityEngine;
using System.Collections;
using System.IO;
using System;

public class CutUI : MonoBehaviour
{
    Vector2 StartPos, TempPos;  // 画布内位置
    Vector3 StMsPos, EdMsPos;  // 屏幕内位置
    public RectTransform SelImg;
    private RectTransform Canvas;
    public GameObject CutBtns, StartCut;

    bool isCutting = false, isPressed = false;

    private void Start()
    {
        CutBtns.SetActive(false);
        SelImg.gameObject.SetActive(false);
        Canvas = GameObject.Find("Canvas").GetComponent<RectTransform>();
    }

    // Update is called once per frame
    void Update()
    {
        if (isCutting && Input.GetMouseButtonDown(0))
        {
            isPressed = true;
            CutBtns.SetActive(false);
            SelImg.gameObject.SetActive(true);
            StMsPos = Input.mousePosition;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(Canvas, StMsPos, null, out StartPos);
            SelImg.anchoredPosition = StartPos;
        }
        if (isCutting && Input.GetMouseButton(0))
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(Canvas, Input.mousePosition, null, out TempPos);
            SelImg.pivot = new Vector2(TempPos.x >= StartPos.x ? 0 : 1, TempPos.y >= StartPos.y ? 0 : 1);
            SelImg.sizeDelta = new Vector2(Mathf.Abs(TempPos.x - StartPos.x), Mathf.Abs(TempPos.y - StartPos.y));
        }
        if (isCutting && isPressed && Input.GetMouseButtonUp(0))
        {
            isPressed = false;
            isCutting = false;
            EdMsPos = Input.mousePosition;
            CutBtns.SetActive(true);
        }
    }

    Rect CutRect;
    private Texture2D Tex;

    IEnumerator CutImage()
    {
        yield return new WaitForEndOfFrame();

        string Name = DateTime.Now.ToString("yyyyMMddHHmmss");

        // 截取选中区域的像素数据
        Vector2Int size = new Vector2Int((int)Mathf.Abs(StMsPos.x - EdMsPos.x), (int)Mathf.Abs(StMsPos.y - EdMsPos.y));
        Vector2Int position = new Vector2Int(Mathf.RoundToInt(Mathf.Min(StMsPos.x, EdMsPos.x)), Mathf.RoundToInt(Mathf.Min(StMsPos.y, EdMsPos.y)));
        Texture2D screenTexture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
        screenTexture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
        screenTexture.Apply();
        Color[] pixels = screenTexture.GetPixels(position.x, position.y, size.x, size.y);

        // 创建新的Texture2D来保存截图
        Tex = new Texture2D(size.x, size.y, TextureFormat.RGB24, false);
        Tex.SetPixels(pixels);
        Tex.Apply();

        // 将Texture2D转换为PNG字节数组
        byte[] bytes = Tex.EncodeToPNG();

        // 保存截图到文件
        string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        string filePath;

        if (Directory.Exists(desktopPath))
        {
            filePath = Path.Combine(desktopPath, Name + ".png");
        }
        else
        {
            string streamingAssetsPath = Application.streamingAssetsPath;
            filePath = Path.Combine(streamingAssetsPath, Name + ".png");
        }

        File.WriteAllBytes(filePath, bytes);
        Debug.Log("截图已保存至:" + filePath);
    }

    public void ClickCut()
    {
        CutBtns.SetActive(false);
        SelImg.gameObject.SetActive(false);
        StartCoroutine(CutImage());
        StartCut.SetActive(true);
    }

    public void ClickCancel()
    {
        CutBtns.SetActive(false);
        SelImg.gameObject.SetActive(false);
        StartCut.SetActive(true);
    }

    public void ClickStartCut()
    {
        isCutting = true;
    }
}

根据自己需求替换脚本

基于SSM框架的智能家政保洁预约系统,是一个旨在提高家政保洁服务预约效率和管理水平的平台。该系统通过集成现代信息技术,为家政公司、家政服务人员和消费者提供了一个便捷的在线预约和管理系统。 系统的主要功能包括: 1. **用户管理**:允许消费者注册、登录,并管理他们的个人资料和预约历史。 2. **家政人员管理**:家政服务人员可以注册并更新自己的个人信息、服务类别和服务时间。 3. **服务预约**:消费者可以浏览不同的家政服务选项,选择合适的服务人员,并在线预约服务。 4. **订单管理**:系统支持订单的创建、跟踪和管理,包括订单的确认、完成和评价。 5. **评价系统**:消费者可以在家政服务完成后对服务进行评价,帮助提高服务质量和透明度。 6. **后台管理**:管理员可以管理用户、家政人员信息、服务类别、预约订单以及处理用户反馈。 系统采用Java语言开发,使用MySQL数据库进行数据存储,通过B/S架构实现用户与服务的在线交互。系统设计考虑了不同用户角色的需求,包括管理员、家政服务人员和普通用户,每个角色都有相应的权限和功能。此外,系统还采用了软件组件化、精化体系结构、分离逻辑和数据等方法,以便于未来的系统升级和维护。 智能家政保洁预约系统通过提供一个集中的平台,不仅方便了消费者的预约和管理,也为家政服务人员提供了一个展示和推广自己服务的机会。同时,系统的后台管理功能为家政公司提供了强大的数据支持和决策辅助,有助于提高服务质量和管理效率。该系统的设计与实现,标志着家政保洁服务向现代化和网络化的转型,为管理决策和控制提供保障,是行业发展中的重要里程碑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值