Unity实用小工具或脚本——录屏工具

一、前言

       本文要讲的录屏不是使用Unity自带的那个截屏方法,因为unity自带的都只能截取unity程序本身显示的画面内容,至于unity程序之外的内容,如电脑桌面上的其他的程序内容是无法录屏的。本文所讲的内容是采用C#本身的截屏方法,效果如图所示:

unity录屏工具示意图

使用的Unity版本为Unity2018.4.17。

二、实现

1、基本思路:先通过C#获取到屏幕的数据,再转换成Unity的Texture,获取很简单,主要是这个转换的过程会比较的棘手。

2、获取截图数据代码如下,获取的是C#里面的Bitmap类型

        Bitmap bit = new Bitmap(shotScreenRect.width,shotScreenRect.height);
        System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bit);
        g.CopyFromScreen(shotScreenRect.x, shotScreenRect.y, 0,0, bit.Size);

先要转换成字节数组Byte[],然后再转成Texture,完整的代码如下

using UnityEngine;
using UnityEngine.UI;
using System.Drawing;
using System.IO;
using System;
using System.Threading;
using System.Drawing.Imaging;

public class CaptureScreen : MonoBehaviour
{
    public RawImage shotShowImage;//显示视频的组件
    public RectInt shotScreenRect;//截图的区域和宽高
    private Thread threadGetData;//截图的线程
    private static byte[] ShotScreenData;//截图的临时数据数组
    private static bool LoadImageOver = false;//没截张图要等到下一次加载完
    void Start()
    {
        threadGetData = new Thread(new ThreadStart(Thread_GetScreenData));
        threadGetData.IsBackground = true;
        threadGetData.Start();
    }

    // Update is called once per frame
    void Update()
    {
        //将截取的图片的数据转换成Texture2D
        if (ShotScreenData != null&&LoadImageOver)
        {
            Texture2D tempTex = new Texture2D(shotScreenRect.width, shotScreenRect.height);
            tempTex.LoadImage(ShotScreenData);
            shotShowImage.texture = tempTex;
            shotShowImage.SetNativeSize();
            LoadImageOver = false;
        }

        if(Input.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit();
        }
    }

    /// 
    /// 开启线程截图获得数据
    /// 
    private void Thread_GetScreenData()
    {
        try
        {
            while (true)
            {
                if (!LoadImageOver)
                {
                    MemoryStream ms = new MemoryStream();
                    CompressImage(GetScreen(), ms);
                    ShotScreenData = ms.ToArray();
                    LoadImageOver = true;
                }
                //Thread.Sleep(1000);
            }
        }
        catch (Exception ee)
        {
            Debug.LogError(ee.Message);
            return;
        }
    }
    private void OnApplicationQuit()
    {
        if(null!= threadGetData)
        threadGetData.Abort();     
    }

    /// 
    /// 截取一张图片
    /// 
    /// 
    private Bitmap GetScreen()
    {
        Bitmap bit = new Bitmap(shotScreenRect.width,shotScreenRect.height);
        System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bit);
        g.CopyFromScreen(shotScreenRect.x, shotScreenRect.y, 0,0, bit.Size);
        return bit;
    }

    ///   
    /// 获取图片编码信息  
    ///   
    /// 编码类型  
    /// ImageCodecInfo  
    private ImageCodecInfo getImageCoderInfo(string coderType)
    {
        ImageCodecInfo[] iciS = ImageCodecInfo.GetImageEncoders();

        ImageCodecInfo retIci = null;

        foreach (ImageCodecInfo ici in iciS)
        {
            if (ici.MimeType.Equals(coderType))
                retIci = ici;
        }
        return retIci;
    }

    /// 
    /// 压缩图片
    /// 
    /// 
    /// 
    private void CompressImage(Bitmap bitmap, MemoryStream ms)
    {
        ImageCodecInfo ici = null;
        Encoder ecd = null;
        EncoderParameter ept = null;
        EncoderParameters eptS = null;
        try
        {
            ici = this.getImageCoderInfo("image/jpeg");
            ecd = Encoder.Quality;
            eptS = new EncoderParameters(1);
            ept = new EncoderParameter(ecd, 10L);
            eptS.Param[0] = ept;
            bitmap.Save(ms, ici, eptS);
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
        finally
        {
            ept.Dispose();
            eptS.Dispose();
        }
    }

}

3、这里使用的Bitmap类型以及其他相关的类都是在System.Drawing.dll的动态链接库中,这个链接库在unity的安装文件中可以找到,但是要注意的是找到正确的版本,我因为一开始使用的是“Unity2018.4.17\Editor\Data\Mono\lib\mono\2.0”下的“System.Drawing.dll",在Editor模式下没有问题,但是发布之后会报“ Fallback handler could not load library Mono/libc.dll”这样的错误,看Log信息应该知道是dll加载的问题,无法加载。直到我一个个试才找到“Unity2018.4.17\Editor\Data\MonoBleedingEdge\lib\mono\unityjit”路径下的这个“System.Drawing.dll"是可以用的版本

4、最后是Unity的设置如图

Unity实用小工具或脚本——录屏工具_第1张图片

三、总结

1、使用unity自带的截图又一定的局限性,想要录取其他的程序或电脑桌面的内容还是要借助C#本身的API;

2、动态链接库的版本一定要控制好。

你可能感兴趣的:(Unity,3D,游戏开发学习笔记)