Unity3D插件:模仿手机截屏效果的截屏插件

在开发游戏的时候有时候会需要截屏分享,或者保存精彩时刻,需要用到截屏,我自己写了个截屏的插件,里面带有动画和声音,后面我将使用方法也放到下面。下面直接放主代码。

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

public class ScreenShot : MonoBehaviour
{
    [HideInInspector]
    public string screenShotPath;//保存路径
    [HideInInspector]
    public Size screenShotSize;//截屏的大小
    [HideInInspector]
    private RawImage image;//截屏动画用
    [HideInInspector]
    public AudioClip screenShotClip;//截屏声音
    private Coroutine coroutine;
    [HideInInspector]
    public string imageName = "";
    [HideInInspector]
    public Texture2D texture;
    // Use this for initialization
    void Start()
    {
#if UNITY_ANDROID
        screenShotPath = "/mnt/sdcard/DCIM/Camera";
#endif
#if UNITY_EDITOR
        screenShotPath = Application.dataPath + "/StreamingAssets/ScreenShotImage";
#endif
        //size = new Size(Screen.width, Screen.height);//默认截全屏
    }

    // Update is called once per frame
    void Update()
    {

    }
    /// <summary>
    /// 截取屏幕像素,不带特效,默认大小
    /// </summary>
    public void TakePhoto()
    {
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot());
        }
    }
    /// <summary>
    ///  截取屏幕像素,带特效,默认大小
    /// </summary>
    /// <param name="effectParent"></param>
    public void TakePhoto(GameObject effectParent)
    {
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot(effectParent));
        }
    }
    /// <summary>
    ///  截取屏幕像素,不带特效,自定义大小
    /// </summary>
    public void TakePhoto(Size size)
    {
        this.screenShotSize = size;
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot());
        }
    }
    /// <summary>
    ///  截取屏幕像素,带特效,自定义大小
    /// </summary>
    /// <param name="effectParent"></param>
    public void TakePhoto(GameObject effectParent, Size size)
    {
        this.screenShotSize = size;
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot(effectParent));
        }
    }
    /// <summary>
    /// 截取某个相机渲染的画面,带特效,默认大小
    /// </summary>
    /// <param name="cam"></param>
    /// <param name="effectParent"></param>
    public void TakePhoto(Camera cam, GameObject effectParent)
    {
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot(cam, effectParent));
        }
    }
    /// <summary>
    /// 截取某个相机渲染的画面,带特效,自定义大小
    /// </summary>
    /// <param name="cam"></param>
    /// <param name="effectParent"></param>
    /// <param name="size"></param>
    public void TakePhoto(Camera cam, GameObject effectParent, Size size)
    {
        this.screenShotSize = size;
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot(cam, effectParent));
        }
    }
    /// <summary>
    /// 截取某个相机渲染的画面,不带特效,自定义大小
    /// </summary>
    /// <param name="cam"></param>
    /// <param name="size"></param>
    public void TakePhoto(Camera cam, Size size)
    {
        this.screenShotSize = size;
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot(cam));
        }
    }
    /// <summary>
    /// 截取某个相机渲染的画面,不带特效,默认大小
    /// </summary>
    /// <param name="cam"></param>
    public void TakePhoto(Camera cam)
    {
        if (coroutine == null)
        {
            coroutine = StartCoroutine(Shot(cam));
        }
    }
    /// <summary>
    /// 截屏(截取某个相机渲染的画面,不带特效)
    /// </summary>
    /// <returns></returns>
    IEnumerator Shot(Camera camera)
    {
        texture = CaptureCamera(camera, new Rect(Screen.width / 2 - screenShotSize.w / 2, Screen.height / 2 - screenShotSize.h / 2, screenShotSize.w, screenShotSize.h));
        yield return new WaitForEndOfFrame();
        var img = texture.EncodeToPNG();
#if UNITY_EDITOR
        if (!Directory.Exists(screenShotPath))//创建生成目录,如果不存在则创建目录  
        {
            Directory.CreateDirectory(screenShotPath);
        }
#endif
        imageName = string.Format("Image{0}.png", GetTimeStamp());
        string file = Path.Combine(screenShotPath, imageName);
        File.WriteAllBytes(file, img);
        coroutine = null;
    }
    /// <summary>
    /// 截屏(截取某个相机渲染的画面,带特效)
    /// </summary>
    /// <returns></returns>
    IEnumerator Shot(Camera camera, GameObject effectParent)
    {
        texture = CaptureCamera(camera, new Rect(Screen.width / 2 - screenShotSize.w / 2, Screen.height / 2 - screenShotSize.h / 2, screenShotSize.w, screenShotSize.h));
        yield return new WaitForEndOfFrame();
        var img = texture.EncodeToPNG();
#if UNITY_EDITOR
        if (!Directory.Exists(screenShotPath))//创建生成目录,如果不存在则创建目录  
        {
            Directory.CreateDirectory(screenShotPath);
        }
#endif
        imageName = string.Format("Image{0}.png", GetTimeStamp());
        string file = Path.Combine(screenShotPath, imageName);
        File.WriteAllBytes(file, img);
        StartCoroutine(ShotEffect(texture, effectParent));
    }
    /// <summary>
    /// 截屏(截取屏幕像素,不带特效)
    /// </summary>
    /// <returns></returns>
    IEnumerator Shot()
    {
        texture = new Texture2D(screenShotSize.w, screenShotSize.h, TextureFormat.RGB24, false);
        yield return new WaitForEndOfFrame();
        texture.ReadPixels(new Rect(Screen.width / 2 - screenShotSize.w / 2, Screen.height / 2 - screenShotSize.h / 2, screenShotSize.w, screenShotSize.h), 0, 0, false);
        texture.Apply();
        var img = texture.EncodeToPNG();
#if UNITY_EDITOR
        if (!Directory.Exists(screenShotPath))//创建生成目录,如果不存在则创建目录  
        {
            Directory.CreateDirectory(screenShotPath);
        }
#endif
        imageName = string.Format("Image{0}.png", GetTimeStamp());
        string file = Path.Combine(screenShotPath, imageName);
        File.WriteAllBytes(file, img);
        coroutine = null;
    }
    /// <summary>
    /// 截屏(截取屏幕像素,带特效)
    /// </summary>
    /// <returns></returns>
    IEnumerator Shot(GameObject effectParent)
    {
        texture = new Texture2D(screenShotSize.w, screenShotSize.h, TextureFormat.RGB24, false);
        yield return new WaitForEndOfFrame();
        texture.ReadPixels(new Rect(Screen.width / 2 - screenShotSize.w / 2, Screen.height / 2 - screenShotSize.h / 2, screenShotSize.w, screenShotSize.h), 0, 0, false);
        texture.Apply();
        var img = texture.EncodeToPNG();
#if UNITY_EDITOR
        if (!Directory.Exists(screenShotPath))//创建生成目录,如果不存在则创建目录  
        {
            Directory.CreateDirectory(screenShotPath);
        }
#endif
        imageName = string.Format("Image{0}.png", GetTimeStamp());
        string file = Path.Combine(screenShotPath, imageName);
        File.WriteAllBytes(file, img);
        StartCoroutine(ShotEffect(texture, effectParent));
    }
    /// <summary>
    /// 截屏效果
    /// </summary>
    /// <param name="texture"></param>
    /// <returns></returns>
    IEnumerator ShotEffect(Texture2D texture, GameObject effectParent)
    {
        float a = 1;
        float scale = 1;
        yield return new WaitForEndOfFrame();
        image = new GameObject("ScreenShot").AddComponent<RawImage>();
        AudioSource source = image.gameObject.AddComponent<AudioSource>();
        if (screenShotClip != null)
        {
            source.clip = screenShotClip;
            source.loop = false;
            source.Play();
        }
        image.transform.SetParent(FindObjectOfType<Canvas>().transform);
        image.transform.localPosition = Vector3.zero;
        image.rectTransform.sizeDelta = new Vector2(Screen.width, Screen.height);
        image.texture = texture;
        while (image.color.a > 0)
        {
            yield return new WaitForSeconds(0.02f);
            image.color = new Color(1, 1, 1, a -= 0.1f);
            image.transform.localScale = new Vector3(scale -= 0.01f, scale -= 0.01f, scale -= 0.01f);
        }
        Destroy(image.gameObject);
        coroutine = null;
    }
    /// <summary>  
    /// 对相机截图。   
    /// </summary>  
    /// <returns>The screenshot2.</returns>  
    /// <param name="camera">Camera.要被截屏的相机</param>  
    /// <param name="rect">Rect.截屏的区域</param>  
    Texture2D CaptureCamera(Camera camera, Rect rect)
    {
        // 创建一个RenderTexture对象  
        RenderTexture rt = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 0);
        // 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机  
        camera.targetTexture = rt;
        camera.Render();
        //ps: --- 如果这样加上第二个相机,可以实现只截图某几个指定的相机一起看到的图像。  
        //ps: camera2.targetTexture = rt;  
        //ps: camera2.Render();  
        //ps: -------------------------------------------------------------------  

        // 激活这个rt, 并从中中读取像素。  
        RenderTexture.active = rt;
        Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
        screenShot.ReadPixels(rect, 0, 0);// 注:这个时候,它是从RenderTexture.active中读取像素  
        screenShot.Apply();

        // 重置相关参数,以使用camera继续在屏幕上显示  
        camera.targetTexture = null;
        //ps: camera2.targetTexture = null;  
        RenderTexture.active = null; // JC: added to avoid errors  
        GameObject.Destroy(rt);

        return screenShot;
    }
    /// <summary>  
    /// 获取时间戳,用来给保存的图片命名
    /// </summary>  
    /// <returns></returns>  
    public static string GetTimeStamp()
    {
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
        return Convert.ToInt64(ts.TotalSeconds).ToString();
    }
}
/// <summary>
/// 大小
/// </summary>
[Serializable]
public struct Size
{
    public int w;
    public int h;
    public Size(int width, int height)
    {
        w = width;
        h = height;
    }
}

只要将插件里预制体拖到场景里就可以,也可以将上面的脚本放到任意的GameObject上。

1

这个代码我新增了对相机截图的功能,并写了好多重载的方法,用来做任意的截图操作,可对截屏的大小和有无特效效果传入不同的参数。个人对于相机截图比较实用,因为在截取是有些时候不需要UI的时候,可以将UI用一个单独的相机去渲染,其他想要截图的可以用另一个相机渲染,这样在截图的时候就不会把UI也截进去了。

插件下载链接:http://pan.baidu.com/s/1jIxJBd8 密码:cw7w

You May Also Like

About the Author: 大腿Plus

1 Comment

发表评论