虽然Unity可以用来做VR的开发引擎,但是在一些功能的实现上两者其实有很多的差异,就截图这个功能来说吧,unity 中的截图与VR中的截图是不一样的,下面就给大家介绍下Unity VR中特定相机截屏问题与实现,一起来看看吧。
Tips:这里就是用HTC Vive头盔下来做为例子。 

 
一、Unity中的常用截图方式
 
unity中常用截图的方式有三种:
 
1. 使用CaptureScreenshot
这个可以参考官方给的例子和代码 https://docs.unity3d.com/ScriptReference/Application.CaptureScreenshot.html


1. void OnMouseDown() {

2.        Application.CaptureScreenshot("Screenshot.png");

3.    }
很简单快捷,就是截取当前屏幕的画面。对于某个镜头的画面或针对场景中位置的截图,这个就不其作用了。
 
2. 使用RenderTexture
这个是使用相机来渲染画面,根据相机的画面来保持纹理,把纹理保存为图片。 
要注意的是在LateUpdate中做了截图的处理;
1.    void LateUpdate()

2.    {

3.  

4.     if (Input.GetKeyDown("s"))

5.    {

6.        StartCoroutine(SaveCameraView());

7.     }

8.  

9.    }
3. 使用Texture2D.ReadPixels
这个也是新建一个Texture2D,然后ReadPixels,z这个是也从屏幕来读取数据。 
所以也有屏幕读取数据的局限
1. Texture2D tex = new Texture2D(Screen.width, Screen.height);

2. tex.ReadPixels(new Rect(0,0,Screen.width,Screen.height),0,0);

3. tex.Apply();
三种方式对比,第二种———使用RenderTexture速度最快。可以参考后面的网站。
 
二、 VR截图注意事项

1. VR中特位置截图
对于截取VR中,若截取全屏使用上面的任意方法都可以。 
但是VR的特点就是相机有玩家来控制,不知道玩家相机的朝向和位置。这个就需要固定位置的截图。 
某个固定位置对象来说,只能使用RenderTexture来实现。 

这个里面有两个问题。 

第一,VR相机的旋转是灵活的,且在vive中,硬件头盔会控制所有相机的旋转。 

第二,就是不能使用于屏幕相关的参数,因为屏幕大小在不一定。 

这里的问题,我们就逐一来解决和说明。

2.实现代码
首先,创建一个RenderTexture,这个做为public,有外面拖拽,在外面定义的RenderTexture来创建好大小和格式。这样容易控制图片大小和格式,策划容易修改。 

其次,解决VR相机能控制所有相机的问题,不能在特定位置预先放置相机,然后在某时刻获取RenderTexture,虽然也可成功截图,但是可能由于相机的角度不停在改变,造成截图移位或倾斜。 
在代码中实时的创建相机。 

代码如下:

1.    private IEnumerator CaptureByRect(string mFileName)

2.     {

3.         //等待渲染线程结束

4.         yield return new WaitForEndOfFrame();

5.         // 实时来创建相机,硬件相机来不及绑定,不会造成偏移和旋转。

6.         GameObject gob = new GameObject();

7.        gob.transform.position=CameraTrans[0].transform.position;

8.        gob.AddComponent();

9.         Camera mCamera =gob.GetComponent();

10.         // 相机投影为正射投影,防止变形和策划调整难度大。

11.       mCamera.orthographic = true;

12.         mCamera.farClipPlane= 20;

13.         mCamera.orthographicSize= 5f;

14.         mCamera.transform.rotation= new Quaternion(0, 0, 0, 0);

15.         //mCamera.cullingMask= 1 << 5;

16.         mCamera.targetTexture= shotTexture;

17.

18.         // get the camera'srender texture

19.         RenderTexture.active= mCamera.targetTexture;

20.

21.         // render thetexture

22.         mCamera.Render();

23.         int height =mCamera.targetTexture.height;

24.         Texture2DcameraImage = new Texture2D(55, 57, TextureFormat.RGB24, false);

25.         cameraImage.ReadPixels(new Rect(100, 105, 55, 57), 0, 0);

26.         cameraImage.Apply();

27.         // store the textureinto a .PNG file

28.         byte[] bytes =cameraImage.EncodeToPNG();

29.         System.IO.File.WriteAllBytes(mFileName,bytes);

30.         Destroy(gob);

31.         //等待渲染线程结束

32.         yield return new WaitForEndOfFrame();

33.         AssetDatabase.Refresh();

34.     }

这里面使用RenderTexture大小为256*256的,根据截图大小来确定Texture读取像素位置。 

这里的代码注释写的还算详细,也容易看懂就不多说了。

3. 关于改进

关于保存图片,这个在使用有卡顿现象。 
试图使用线程来解决,但是策划说效果不明显,还不如不使用。

1.  new System.Threading.Thread(() =>

2.    {

3.         System.Threading.Thread.Sleep(100);

4.         System.IO.File.WriteAllBytes(mFileName, bytes);

5.

6.     }).Start();

个人感觉,线程没有问题,可能是创建线程需要时间,可以尝试使用线程池来。