Unity3d之截图方法

Unity3d  三种截屏方法:


1、使用Application类下的CaptureScreenshot方法。

[csharp]  view plain copy 派生到我的代码片
  1. void CaptureScreen()   
  2. {  
  3.     Application.CaptureScreenshot("Screenshot.png", 0);  
  4. }  

 

这个方法,截取的是某一帧时整个游戏的画面,或者说是全屏截图吧。

a、不能针对某一个相机(camera)的画面,进行截图。

b、对局部画面截图,实现起来不方便,效率也低,不建议在项目中使用:

虽然CaptureScreenshot这个方法呢,本身是不要做到这一点的。但是我们可以走曲线救国的路线来实现它。思路是这样的:你可以先用这个方法截图一个全屏,然后通过路径获取到这个截图;接下来就通过相关的图形类来,取得这个截图的局部区域并保存下来,这样就能得到一个局部截图了。在这里我就不实现它了,不过有兴趣的可以试试,肯定是可以实现的。


2、这第二个截图的方法是,使用Texture2d类下的相关方法,也可实现截图功能。

[csharp]  view plain copy 派生到我的代码片
  1. /// <summary>  
  2. /// Captures the screenshot2.  
  3. /// </summary>  
  4. /// <returns>The screenshot2.</returns>  
  5. /// <param name="rect">Rect.截图的区域,左下角为o点</param>  
  6. Texture2D CaptureScreenshot2(Rect rect)   
  7. {  
  8.     // 先创建一个的空纹理,大小可根据实现需要来设置  
  9.     Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24,false);  
  10.   
  11.     // 读取屏幕像素信息并存储为纹理数据,  
  12.     screenShot.ReadPixels(rect, 0, 0);  
  13.     screenShot.Apply();  
  14.   
  15.     // 然后将这些纹理数据,成一个png图片文件  
  16.     byte[] bytes = screenShot.EncodeToPNG();  
  17.     string filename = Application.dataPath + "/Screenshot.png";  
  18.     System.IO.File.WriteAllBytes(filename, bytes);  
  19.     Debug.Log(string.Format("截屏了一张图片: {0}", filename));  
  20.   
  21.     // 最后,我返回这个Texture2d对象,这样我们直接,所这个截图图示在游戏中,当然这个根据自己的需求的。  
  22.     return screenShot;  
  23. }  
截全屏(如下图, 注:有ui):
CaptureScreenshot2( new Rect( Screen.width*0f, Screen.height*0f, Screen.width*1f, Screen.height*1f));


截中间4分之(如下图):
CaptureScreenshot2( new Rect( Screen.width*0.25f, Screen.height*0.25f, Screen.width*0.5f, Screen.height*0.5f));


这里使用了几个Texture2d类的方法,使用上也有一些要注意的地方,自己看吧。

当然,这个方法也不要到实现针对某个相机的截图的功能。不过关键接口已经出现了,它就是Texture2d.ReadPixels(),这段就不说了,接着往下看吧!

3、这第三个方法,可以针对某个相机进行截图。我截取VR 相机中的图片,并且将图片同时显示到手柄上的UI 上

这样的话,我就可截下,我的Avatar在游戏中场景中所看的画面了,UI界面(用一个专门的camera显示)什么的是不应该有的。要做到这一点,我们应该将分出一个camera来专门显示ui界面,用另一个camera相机来场景显示场景画面。然后,我们只对场景相机进行截屏就是了。所以这关键点就是:如何实现对某个相机进行截屏了。这里用到一个新的类是RenderTexture。

代码如下:

using System.Collections;

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class ScreenShootUI : MonoBehaviour {


    public RawImage shootImage;
    public static ScreenShootUI _instance;
    void Awake()
    {
        _instance = this;
    }
// Use this for initialization
void Start () {
        shootImage = transform.Find("shootImage").GetComponent<RawImage>();
}

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

}
    
    public void UpdateUI( Texture t )
    {  
        Texture temp = (Texture)t; 
        shootImage.texture = t ;
     //   shootImage.material.mainTexture = t;
    }


}


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


public class ScreenShootManager : MonoBehaviour {


     private FunctinState state = FunctinState.Screenshot;
     private ScreenShootManager() { }
    private static ScreenShootManager _instacne;
    public static ScreenShootManager GetInstance()
    {
        if(_instacne = null)
        {
            _instacne = new ScreenShootManager();
        }
        return  _instacne;
    }
    public Camera _camera;
    public string picturename;
    public static  string filename;
// Use this for initialization
void Start () {
        filename = "ScreenShootSictures";
        picturename = "截图";
        CreatFile();
 


    }

// Update is called once per frame
void Update () {
        if (Input.GetMouseButtonDown(0)) {
            ScreenShootFun();


        }
          


    }
    public  DirectoryInfo dir;
    public   void CreatFile()
    {
        string str = Application.streamingAssetsPath + "/" + filename;
         dir = new DirectoryInfo(str);
        if (!dir.Exists){
            dir.Create();
            
        }
        else
        {
            Debug.Log("已经创建");
        }
    }


    private  int number;
    public  void NameChange()
    {
        FileInfo[] files = dir.GetFiles();
         number = dir.GetFiles().Length;
        picturename = "截图" + number.ToString();


    }


    public void ScreenShootFun() {
        if (FunctionManager.GetInstance().currentState != state) return;
        NameChange();
        StartCoroutine(ScreenShoot());
    }


    private  IEnumerator  ScreenShoot()
    {
       
        //等待所有的摄像机和GUI被渲染完成。
        yield return new WaitForEndOfFrame();
        RenderTexture rt = new RenderTexture(Screen.width, Screen.height, 16);
        // 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机  
        _camera.targetTexture = rt;
        _camera.Render();
        //ps: --- 如果这样加上第二个相机,可以实现只截图某几个指定的相机一起看到的图像。  
        //ps: camera2.targetTexture = rt;  
        //ps: camera2.Render();  
        //ps: -------------------------------------------------------------------   
        // 激活这个rt, 并从中中读取像素。  
        RenderTexture.active = rt;
        ScreenShootUI._instance.UpdateUI(rt);  //  将截图显示到UI面板上
        Texture2D screenShot = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
        screenShot.ReadPixels(new Rect(0, 0, screenShot.width, screenShot.height), 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);        // 没有销毁一直在内存中 
        // 最后将这些纹理数据,成一个png图片文件  
        byte[] bytes = screenShot.EncodeToPNG();
        string path = Application.streamingAssetsPath + "/" +filename+"/"+ picturename;
        File.WriteAllBytes(path, bytes);
        Debug.Log(string.Format("截屏了一张照片: {0}", picturename));
    }
 

}

https://blog.csdn.net/highning0007/article/details/37991787


补充:

Rect

是一个结构体,主要保存了, xmin   xmax  ymin  ymax  center 等信息,每一个new 出来的结构体对象()中储存

是一个矩形方块的数据,将结构体对象传入方法中,会调用对应的数据,(构造时数据数据是对应的),对比Vector3,四元素,

只不过使用方式不一样,存储信息不同

rectTransform  是类,继承Transform 区别一下







猜你喜欢

转载自blog.csdn.net/july_unity/article/details/79810944