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