启用相机访问功能
必须声明“WebCam”功能,应用才能使用 相机。
- 在Unity 编辑器,导航到“编辑>项目设置播放器”页面,转到播放器设置>
- 选择“Windows 应用商店”选项卡
- 在“发布设置>功能”部分中,检查 WebCam 和麦克风功能
一次只能对相机执行一次作。 可以在 2018 年及 Unity 及更早版本或 UnityEngine.Windows.WebCam.Mode Unity 2019 及更高版本中检查相机当前处于UnityEngine.XR.WSA.WebCam.Mode哪种模式。 可用模式为照片、视频或无。
照片捕获
命名空间 (之前Unity 2019) :UnityEngine.XR.WSA.WebCam
命名空间 (Unity 2019 及更高版本) :UnityEngine.Windows.WebCam
类型:PhotoCapture
PhotoCapture 类型允许使用照片视频相机拍摄静态照片。 使用 PhotoCapture 拍摄照片的一般模式如下:
- 创建 PhotoCapture 对象
- 使用所需的设置创建 CameraParameters 对象
- 通过 StartPhotoModeAsync 启动照片模式
- 拍摄所需的照片
- (可选) 与该图片交互
- 停止照片模式并清理资源
PhotoCapture 的常见设置
对于所有三个用途,请从上面的前三个步骤开始
首先创建 PhotoCapture 对象
private void Start()
{
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
接下来,存储对象、设置参数并启动照片模式
private PhotoCapture photoCaptureObject = null;
void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
photoCaptureObject = captureObject;
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
CameraParameters c = new CameraParameters();
c.hologramOpacity = 0.0f;
c.cameraResolutionWidth = cameraResolution.width;
c.cameraResolutionHeight = cameraResolution.height;
c.pixelFormat = CapturePixelFormat.BGRA32;
captureObject.StartPhotoModeAsync(c, false, OnPhotoModeStarted);
}
最后,你还将使用此处提供的相同清理代码
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
photoCaptureObject.Dispose();
photoCaptureObject = null;
}
完成这些步骤后,你可以选择要捕获的照片类型。
将照片捕获到文件
最简单的作是将照片直接捕获到文件。 照片可以保存为 JPG 或 PNG。
如果成功启动照片模式,请拍摄照片并将其存储在磁盘上
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
string filename = string.Format(@"CapturedImage{0}_n.jpg", Time.time);
string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);
photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
}
else
{
Debug.LogError("Unable to start photo mode!");
}
}
将照片捕获到磁盘后,退出照片模式,然后清理对象
void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
Debug.Log("Saved Photo to disk!");
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
else
{
Debug.Log("Failed to save Photo to disk");
}
}
使用位置将照片捕获到 Texture2D
将数据捕获到 Texture2D 时,此过程类似于捕获到磁盘。
按照上述设置过程进行作。
在 OnPhotoModeStarted 中,将帧捕获到内存。
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
else
{
Debug.LogError("Unable to start photo mode!");
}
}
然后,你将结果应用于纹理,并使用上面的常见清理代码。
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
if (result.success)
{
// Create our Texture2D for use and set the correct resolution
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
// Copy the raw image data into our target texture
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
// Do as we wish with the texture such as apply it to a material, etc.
}
// Clean up
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
可定位相机
若要将此纹理放置在场景中并使用可定位的相机矩阵显示它,请将以下代码添加到 检查 OnCapturedPhotoToMemoryresult.success :
if (photoCaptureFrame.hasLocationData)
{
photoCaptureFrame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix);
Vector3 position = cameraToWorldMatrix.GetColumn(3) - cameraToWorldMatrix.GetColumn(2);
Quaternion rotation = Quaternion.LookRotation(-cameraToWorldMatrix.GetColumn(2), cameraToWorldMatrix.GetColumn(1));
photoCaptureFrame.TryGetProjectionMatrix(Camera.main.nearClipPlane, Camera.main.farClipPlane, out Matrix4x4 projectionMatrix);
}
Unity提供了示例代码,用于将投影矩阵应用到论坛上的特定着色器。
捕获照片并与原始字节交互
若要与内存帧的原始字节交互,请按照上述设置步骤和 OnPhotoModeStarted 中的设置步骤作,就像将照片捕获到 Texture2D 一样。 区别在于 OnCapturedPhotoToMemory ,你可以在其中获取原始字节并与之交互。
在此示例中,你将创建一个 列表 ,以便通过 SetPixels ()
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
if (result.success)
{
List<byte> imageBufferList = new List<byte>();
// Copy the raw IMFMediaBuffer data into our empty byte list.
photoCaptureFrame.CopyRawImageDataIntoBuffer(imageBufferList);
// In this example, we captured the image using the BGRA32 format.
// So our stride will be 4 since we have a byte for each rgba channel.
// The raw image data will also be flipped so we access our pixel data
// in the reverse order.
int stride = 4;
float denominator = 1.0f / 255.0f;
List<Color> colorArray = new List<Color>();
for (int i = imageBufferList.Count - 1; i >= 0; i -= stride)
{
float a = (int)(imageBufferList[i - 0]) * denominator;
float r = (int)(imageBufferList[i - 1]) * denominator;
float g = (int)(imageBufferList[i - 2]) * denominator;
float b = (int)(imageBufferList[i - 3]) * denominator;
colorArray.Add(new Color(r, g, b, a));
}
// Now we could do something with the array such as texture.SetPixels() or run image processing on the list
}
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
视频捕获
命名空间 (之前Unity 2019) :UnityEngine.XR.WSA.WebCam
命名空间 (Unity 2019 及更高版本) :UnityEngine.Windows.WebCam
类型:VideoCapture
VideoCapture 的功能类似于 PhotoCapture。 唯一的两个区别是,必须指定每秒帧数 (FPS) 值,并且只能直接以 .mp4 文件的形式保存到磁盘。 使用 VideoCapture 的步骤如下:
- 创建 VideoCapture 对象
- 使用所需的设置创建 CameraParameters 对象
- 通过 StartVideoModeAsync 启动视频模式
- 开始录制视频
- 停止录制视频
- 停止视频模式并清理资源
首先创建 VideoCapture 对象 VideoCapture m_VideoCapture = null;
void Start ()
{
VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}
接下来,设置录制和启动所需的参数。
void OnVideoCaptureCreated(VideoCapture videoCapture)
{
if (videoCapture != null)
{
m_VideoCapture = videoCapture;
Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();
CameraParameters cameraParameters = new CameraParameters();
cameraParameters.hologramOpacity = 0.0f;
cameraParameters.frameRate = cameraFramerate;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
m_VideoCapture.StartVideoModeAsync(cameraParameters,
VideoCapture.AudioState.None,
OnStartedVideoCaptureMode);
}
else
{
Debug.LogError("Failed to create VideoCapture Instance!");
}
}
启动后,开始录制
void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
if (result.success)
{
string filename = string.Format("MyVideo_{0}.mp4", Time.time);
string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);
m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
}
}
开始录制后,可以更新 UI 或行为以启用停止。 在这里,你只需记录。
void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Started Recording Video!");
// We will stop the video from recording via other input such as a timer or a tap, etc.
}
例如,稍后需要使用计时器或用户输入停止录制。
// The user has indicated to stop recording
void StopRecordingVideo()
{
m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}
录制停止后,停止视频模式并清理资源。
void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Stopped Recording Video!");
m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}
void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
m_VideoCapture.Dispose();
m_VideoCapture = null;
}
疑难解答
- 没有可用的解决方案
- 确保在项目中指定 了 WebCam 功能。
下一个开发检查点
如果你遵循我们制定的Unity开发检查点之旅,则你正在探索混合现实平台功能和 API。 在此处,可以继续学习下一主题:
或者直接跳转到在设备或模拟器上部署应用:
可以随时返回到Unity开发检查点。