|
洪流学堂,让你快人几步。你好,我是郑洪智。
洪流学堂公众号回复捉妖,可以获取本教程的源码工程。
<hr/>小新:“我们接下来是不是需要将显示融合到屏幕上,才能称得上是AR呢?”
大智:“没错,屏幕式AR就是通过摄像头获取现实世界的图像,显示在屏幕上,然后和虚拟的物体叠加显示。我们今天就来实现这个摄像头图像做背景。”
2.摄像头图像做背景
要使用摄像头图像做背景,那首先需要获取到摄像头的图像。在Unity中读取摄像头的数据主要需要用到WebCamTexture这个类。
核心代码如下:
IEnumrator Start()
{
// 请求摄像头权限
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
// 如果获取到摄像头权限
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
// 获取所有的摄像头设备
WebCamDevice[] devices = WebCamTexture.devices;
if (devices != null)
{
// 索引为0的摄像头一般为后置摄像头,参数分别为设备名称、图像宽度、高度、刷新率
WebCamTexture tex = new WebCamTexture(devices[0].name, width, height, fps);
// 实时获取摄像头的画面
tex.Play();
}
}
}大智:“那么如何将摄像头的图像作为游戏背景现实呢?”
小新:“这个简单,直接使用全屏的UI图片就可以了吧?”
大智:“再详细点呢?”
小新:“恩么。。。应该是使用UI里面的RawImage组件,然后将WebCamTexture赋值给这个组件的texture属性。”
大智:“那你想到一个问题没有?我们需要在这个背景上显示3D模型,也就是我们要抓的妖怪,如何设置呢?”
小新:“哦哦,对哦,那我们应该把UI设置为3D的UI,由于UI是跟随相机移动的,可以设置Canvas为Screen Space - Camera。”
大智:“嗯,那我们试试看喽。”
接下来我们需要把相机的画面赋给这个RawImage组件的texture,最后完整的代码如下:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class WebCameraBackground : MonoBehaviour
{
RawImage cameraImage;
private WebCamTexture webCamTex;
IEnumerator Start()
{
cameraImage = GetComponent<RawImage>();
// 请求摄像头权限
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
// 如果获取到摄像头权限
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
// 获取所有的摄像头设备
WebCamDevice[] devices = WebCamTexture.devices;
if (devices != null)
{
// 索引为0的摄像头一般为后置摄像头,参数分别为设备名称、图像宽度、高度、刷新率
webCamTex = new WebCamTexture(devices[0].name, 800, 1280, 30);
// 实时获取摄像头的画面
webCamTex.Play();
cameraImage.texture = webCamTex;
}
}
}
}最后将这个代码拖到RawImage这个物体上,就可以发布到真机上测试查看了!
小新:“这发布出来以后有点不太对,只有手机横着的时候,摄像头显示的图像方向和实际是一致的,其他的都不对。”
大智:“这是因为WebCamTexture返回的图像,实际上会根据手机的朝向有一定的旋转,我们把下面的代码加进来测试一下看看。”
private void OnGUI()
{
// 使用下面的旋转角度(顺时针)来旋转摄像头,以保证正确的朝向
GUILayout.Label(webCamTex.videoRotationAngle.ToString());
// 摄像头的视频是否垂直翻转
GUILayout.Label(webCamTex.videoVerticallyMirrored.ToString());
}使用竖屏时,你会看到第一个值显示的是90,意味着我们需要将图像顺时针旋转90度,才是正确的朝向。
小新:“我试着改了一下,还是不对,智哥你来吧。”
大智:“那我就直接上代码了,首先你把RawImage的Anchor的位置直接设置到中心就行。因为后面我们需要通过代码来修改这个RawImage的旋转和尺寸,否则会有冲突。”
具体完整代码如下:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class WebCameraBackground : MonoBehaviour
{
RawImage cameraImage;
private RectTransform rectTransform;
private WebCamTexture webCamTex;
private int lastRotationAngle;
IEnumerator Start()
{
cameraImage = GetComponent<RawImage>();
rectTransform = GetComponent<RectTransform>();
// 请求摄像头权限
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
// 如果获取到摄像头权限
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
// 获取所有的摄像头设备
WebCamDevice[] devices = WebCamTexture.devices;
if (devices != null)
{
// 索引为0的摄像头一般为后置摄像头,参数分别为设备名称、图像宽度、高度、刷新率
webCamTex = new WebCamTexture(devices[0].name, 800, 1280, 30);
// 实时获取摄像头的画面
webCamTex.Play();
cameraImage.texture = webCamTex;
}
}
}
private void Update()
{
if (webCamTex != null && lastRotationAngle != webCamTex.videoRotationAngle)
{
OnOrientationChanged();
lastRotationAngle = webCamTex.videoRotationAngle;
}
}
private void OnOrientationChanged()
{
// 旋转rawimage,为什么加一个负号呢?因为rawimage的z轴是背对图像的,直接使用videoRotationAngle旋转,相对于图片是逆时针旋转
transform.localRotation = Quaternion.Euler(0, 0, -webCamTex.videoRotationAngle);
// 判断是否是竖屏,竖屏时由于旋转的关系,需要将width和height调换
if (webCamTex.videoRotationAngle % 180 != 0)
rectTransform.sizeDelta = new Vector2(Screen.height, Screen.width);
else
rectTransform.sizeDelta = new Vector2(Screen.width, Screen.height);
}
private void OnGUI()
{
// 使用下面的旋转角度(顺时针)来旋转摄像头,以保证正确的朝向
GUILayout.Label(webCamTex.videoRotationAngle.ToString());
// 摄像头的视频是否垂直翻转
GUILayout.Label(webCamTex.videoVerticallyMirrored.ToString());
}
}小新:“旋转rawimage,为什么加一个负号呢?”
大智:“因为webCamTex.videoRotationAngle的返回值是相对于图像需要顺时针旋转一定的角度。也就是如下图所示:”
大智:“如果以Unity的左手坐标系来看的话,这个角度所对应的旋转轴应该是朝屏幕外的方向。但实际上rawimage的z轴是朝向屏幕内的,所以刚好相反,简单来计算就是取videoRotationAngle的负值即可。”
总结
大智:“今天学习了用Unity开发《一起来捉妖》的第二部分,实现了摄像头作为游戏的背景。”
小新:“加上背景以后呢,真的有些AR的感觉了呢。”
洪流学堂公众号回复捉妖,可以获取本教程的源码工程。
https://www.zhihu.com/video/1110263763374161920
今日思考题
大智:“动手将今天的工程部署到真机上体验一下。” 小新:“好嘞!” 大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”
推荐阅读
- Unity开发《一起来捉妖》教程 | 1.陀螺仪控制相机
- Unity 2019.1 中文更新日志速览版
- UnityWebRequest详解
- Unity中编码Encoding脱坑指南
- Unity中的Git最佳实践
- Unity2019更新规划速览,将有官方的可视化编程!
- Unity运行时更新带来了什么?
- Unity2018.3新功能 | Prefab嵌套和变体
- Unity3d中的百度语音识别及语音合成
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|