关于Unity的截屏方法

作者: magicbell | 来源:发表于2016-11-07 19:59 被阅读734次

    序:开始决定写东西,内容不限,关于工作内容的,关于自己业余研究的,关于生活的...因为只有写下来,思路才会更清晰,印象才会更深刻,更可以Share。ps:我是个女码农,现在从事Unity游戏、应用的开发。不要试图问一个女生为什么选择这个职业,做了就是做了,并且要做好。


    Ok,well这次简短点,我最近碰到一个关于Unity截屏的问题。用过的人很快会想到两种截屏的方式:

    1. Application.CaptureScreenshot(string file name),这会截取当前屏幕保存为png格式,存放在Application.dataPath(PC/Mac),Application.persistantDataPath(移动设备)。如果需要获取图片用作显示,或保存在系统照片集下,就需要通过www的方式读取后再做处理,不是很方便。

    2. Texture2D.ReadPixels(Rect source, int destX, int destY, bool recaculateMipmaps=true), 这会读取指定区域内的屏幕像素至一张texture中,用于UI显示、保存等。相比方法一更方便直观。我们大多数都是采用该方法。

    但是,最近碰到的问题是,在一些低端性能差点的Android设备上,用以上两种方式截出来的图是黑色(像素值全是0),用了coroutine方式WaitEndOfFrame,试图修改Texture2D的format、size,放在Monobehavior.OnPostRender()中...试过想到的各种方法均无效,也没有报warning、error。就想到尝试用第三种方式来实现:RenderTexture。

    通过将Camera的内容渲染到一张RT中,然后用Texture2D.ReadPixels()方法从当前的RT中读取,结果可行!代码如下:

    public static Texture2D CaptureCamera(Rect rect,  params Camera[] cameras)
    {
        RenderTexture rt = new RenderTexture ((int)Screen.width, (int)Screen.height, 24);
        //临时设置相关相机的targetTexture为rt, 并手动渲染相关相机
        for (int i=0; i<cameras.Length; i++)
        {
            if(cameras[i] != null)
            {
                cameras[i].targetTexture=rt;
                cameras[i].Render();
            }
        }
    
       //激活这个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继续在屏幕上显示
       for(int i=0; i<cameras.Length; i++)
       {
           if(cameras[i] !=null)
              cameras[i].targetTexture = null;
       }
                
       RenderTexture.active = null;
       GameObject.Destroy(rt);
    
       return screenShot;
    }
    

    分析原因,有如下推断:Android渲染采用了双缓冲,而前两种方式是从绘制到当前屏幕的framebuffer中读数据,当设备运行慢时,在Unity调用接口所读到的数据是从正在写入的framebuffer里面的,还没有swap送入屏幕显示,所以读到的像素值为0。采用RenderTexture方式将Camera绘制内容写入texture中,从该texture中读取数据能够解决上述问题,确保数据有效。
    这是我的一个推断,可能是其他原因,搜索以及debug无果,希望以后的开发中能彻底知晓原因。

    相关文章

      网友评论

        本文标题:关于Unity的截屏方法

        本文链接:https://www.haomeiwen.com/subject/tjhouttx.html