AR项目需求,Unity打开摄像头做为背景渲染占满全屏~ Unity对设备硬件操做的API并非太友好~打开一个摄像头,渲染到屏幕上也都得本身写,虽然步骤少,提取摄像头texture,渲染到UGUI上(本文采起的是UGUI的方案),这时候涉及到一个屏幕适配的问题,以及Unity层级问题。。。canvas
下面先贴上代码和场景配置~ 再说一些坑。。code
using UnityEngine; using System.Collections; using UnityEngine.UI; public class STCamDeviceController : MonoBehaviour { WebCamTexture camTexture; CanvasScaler CanScaler; Camera ca; Image img; void Start () { img = GetComponentInChildren<Image>(); CanScaler = GetComponentInChildren<CanvasScaler> (); CanScaler.referenceResolution = new Vector2 (Screen.width, Screen.height); ca = GetComponentInChildren<Camera> (); ca.orthographicSize = Screen.width / 100.0f/ 2.0f; img.transform.localScale = new Vector3 (-1, -1, -1); img.rectTransform.anchorMin = new Vector2 (0.5f, 0.5f); img.rectTransform.anchorMax = new Vector2 (0.5f, 0.5f); img.rectTransform.pivot = new Vector2(0.5f,0.5f); img.rectTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, Screen.height); img.rectTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, Screen.width); // 设备不一样的坐标转换 #if UNITY_IOS || UNITY_IPHONE img.transform.Rotate (new Vector3 (0, 180, 90)); #elif UNITY_ANDROID img.transform.Rotate (new Vector3 (0, 0, 90)); #endif StartCoroutine(CallCamera()); } IEnumerator CallCamera() { yield return Application.RequestUserAuthorization(UserAuthorization.WebCam); if (Application.HasUserAuthorization(UserAuthorization.WebCam)) { if (camTexture != null) camTexture.Stop(); WebCamDevice[] cameraDevices = WebCamTexture.devices; string deviceName = cameraDevices[0].name; camTexture = new WebCamTexture(deviceName,Screen.height,Screen.width,60); img.canvasRenderer.SetTexture(camTexture); camTexture.Play(); } } }
此脚本挂在做为打开相机渲染背景的Canvas上~ (UI是另一个相对独立的Canvas)。。场景里面的配置以下~orm
再看CameraGBCanvas 和 CameraBG 的配置~ 由于背景image的大小约束都是经过代码动态设置的~blog
配置如上~ 说说实现思路和一些坑~文档
首先,第一步。打开相机~
在Start方法里经过 IEnumerator 开启了相机。判断用户是否给了摄像头哦权限,接下来获取设备列表,取第0个就是后置摄像头,取出texture而且渲染到 image上,,这里能够看到取出的texture的 宽等于其高,,高等于其宽,,那是由于取出的textur绕z轴旋转了90度。这里先作了宽高对调~string
第二步,渲染成功后背景Image屏幕适配问题。。it
a. 首先调整屏幕适配宽高参考值,就为当前屏幕宽高
代码:io
CanScaler = GetComponentInChildren<CanvasScaler> (); CanScaler.referenceResolution = new Vector2 (Screen.width, Screen.height);
b.摄像头渲染背景的相机已经调整为正交模式了,其中有一个正交大小的值 orthographicSize 。。根据官方文档的说法是当处于垂直转台的时候等于高的一半,也就是代码以下~form
ca = GetComponentInChildren<Camera> (); ca.orthographicSize = Screen.width / 100.0f/ 2.0f;
c. 接着作image旋转处理class
img.transform.localScale = new Vector3 (-1, -1, -1); img.rectTransform.anchorMin = new Vector2 (0.5f, 0.5f); img.rectTransform.anchorMax = new Vector2 (0.5f, 0.5f); img.rectTransform.pivot = new Vector2(0.5f,0.5f); img.rectTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, Screen.height); img.rectTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, Screen.width);
d.最后根据设备不一样,判断image的rotae,这一点感受Unity一点儿都不友好,为何不能本身判断设备自动适配坐标系统叻? Unity API 给个人感受是发展空间还挺大的,好多地方都须要改进~
// 设备不一样的坐标转换 #if UNITY_IOS || UNITY_IPHONE img.transform.Rotate (new Vector3 (0, 180, 90)); #elif UNITY_ANDROID img.transform.Rotate (new Vector3 (0, 0, 90)); #endif