Unity使用WebCamTexture 实现手机前后摄像头调用

本文介绍如何在Unity中调用外部摄像头,并展示了使用RawImage显示摄像头画面的方法。文章提供了具体的代码实现,包括如何通过WebCamTexture获取摄像头图像,以及如何进行简单的播放、暂停和停止操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近搞unity外部摄像头调用,参考了下网上的说法,发现有的已经是很早的写法了,这里自己尝试改了点,以作参考。

难点:获取摄像头

1,WebCamTexture个人认为是Unity封装好的摄像头传过来的图像信息;

2,将WebCamTexture的对象赋值给一个Texture(载体,即游戏物体,可以是GUITexture、Render.Material.Texture、RawImage.Texture等)

3,上面说到的载体Texture调用Play(),Pause(),Stop()即可完成简单的播放,暂停,停止。

4,WebCamTexture.devices属性代表当前的所有设备的引用,实例化WebCamTexture时根据devices中的名字即可代表是哪个摄像头。

下面是用RawImage显示的例子,用到的按钮等要自己创建。

以上是个人理解,大笑如有错误欢迎指正!!!!

using UnityEngine;

using System.Collections;
using UnityEngine.UI;

public class WebCamera : MonoBehaviour {

//组件引用
private RawImage go_rawImageTexture;
public Button[] button;
public Text debugText;
public Image photoImg;

private WebCamTexture _webcamTexFront;
private WebCamTexture _webcamTexBack;
WebCamTexture webcamTexture;
//前后摄像头
public int m_devID = 0;
//宽高比
public float aspect = 9f / 16f;

private string m_deviceName;
public string m_photoName;
public string m_photoPath;

void Start()
{
Debug.Log(Application.persistentDataPath);
go_rawImageTexture = transform.Find("RawImage").GetComponent<RawImage>();

button[0].onClick.AddListener(Play);
button[1].onClick.AddListener(Stop);
button[2].onClick.AddListener(cameraSwitch);
button[3].onClick.AddListener(TakePhoto);
//webcamTexture = new WebCamTexture();

如果有后置摄像头,调用后置摄像头
//for (int i = 0; i < WebCamTexture.devices.Length; i++)
//{
// if (!WebCamTexture.devices[i].isFrontFacing)
// {
// webcamTexture.deviceName = WebCamTexture.devices[i].name;
// break;
// }
//}
// go_rawImageTexture.texture = webcamTexture;
//webcamTexture.Play();

//WebCamDevice[] devices = WebCamTexture.devices;
//for( var i = 0 ; i < devices.Length ; i++ ){
// Debug.Log(devices[i].name);

// }
}

public delegate void onComplete(Sprite sprite);

public WebCamTexture webCamera
{
get
{
m_deviceName = WebCamTexture.devices[m_devID].name;

if (m_devID == 0)
{
if (_webcamTexBack == null)
{
// Checks how many and which cameras are available on the device
foreach (WebCamDevice device in WebCamTexture.devices)
{
if (!device.isFrontFacing)
{
m_deviceName = device.name;
_webcamTexBack = new WebCamTexture(m_deviceName, Screen.width, (int)(Screen.width * aspect));
}
}
}
return _webcamTexBack;
}
else
{
if (_webcamTexFront == null)
{
// Checks how many and which cameras are available on the device
foreach (WebCamDevice device in WebCamTexture.devices)
{
if (device.isFrontFacing)
{
m_deviceName = device.name;
_webcamTexFront = new WebCamTexture(m_deviceName, Screen.width, (int)(Screen.width * aspect));
}
}
}
return _webcamTexFront;
}
}
}
void Play()
{
go_rawImageTexture.texture = webCamera;
webCamera.Play();
//webcamTexture.Play();
}
void Stop()
{

webCamera.Stop();
//webcamTexture.Stop();
}
public void cameraSwitch()
{
// Checks how many and which cameras are available on the device
foreach (WebCamDevice device in WebCamTexture.devices)
{
if (m_deviceName != device.name)
{
webCamera.Stop();
m_devID++;
if (m_devID >= WebCamTexture.devices.Length) m_devID = 0;
webCamera.deviceName = device.name;

Debug.Log("m_devID" + m_devID);
Debug.Log("m_deviceName" + device.name);
debugText.text="ID:"+m_devID+"Name:"+device.name;
webCamera.Play();
break;
}
}
}
void TakePhoto()
{
takePicture((delegate (Sprite sp)
{
photoImg.sprite = sp;
}));
}

public void takePicture(onComplete callback)
{

StartCoroutine(GetTexture(callback));
}

//捕获照片
//获取截图
public IEnumerator GetTexture(onComplete callback)
{
webCamera.Pause();
yield return new WaitForEndOfFrame();

//save
Texture2D t = new Texture2D(Screen.width, (int)(Screen.width * aspect));
t.ReadPixels(new Rect(0, 0, Screen.width, (int)(Screen.width * aspect)), 0, 0, false);
t.Apply();
byte[] byt = t.EncodeToPNG();
m_photoName = Time.time + ".png";
m_photoPath = Application.persistentDataPath + "/" + m_photoName;
System.IO.File.WriteAllBytes(m_photoPath, byt);

//load image
WWW www = new WWW("file://" + m_photoPath);
yield return www;

Sprite sprite = Sprite.Create(www.texture, new Rect(0, 0, Screen.width, (int)(Screen.width * aspect)), new Vector2(0.5f, 0.5f));
//回调
callback(sprite);
}

// 录像
// 连续捕获照片
public IEnumerator SeriousPhotoes()
{
while (true)
{
yield return new WaitForEndOfFrame();
Texture2D t = new Texture2D(400, 300, TextureFormat.RGB24, true);
t.ReadPixels(new Rect(0, 0, Screen.width, (int)(Screen.width * aspect)), 0, 0, false);
t.Apply();
print(t);
byte[] byt = t.EncodeToPNG();
System.IO.File.WriteAllBytes(Application.dataPath + "/MulPhotoes/" + Time.time.ToString().Split('.')[0] + "_" + Time.time.ToString().Split('.')[1] + ".png", byt);
// using System.Threading;
// Thread.Sleep(300);
}
}

}

下载地址:

链接:https://pan.baidu.com/s/1bo25P9P 密码:u9oj

<think>好的,我现在要解决用户的问题:在Unity使用WebCamTexture开发时,客户端无法调取摄像头。用户可能已经按照之前的建议在Unity中编写了代码,但实际运行时遇到了问题。我需要分析可能的原因并提供解决方案。 首先,用户的情况是客户端无法调取摄像头,这可能涉及多个方面,比如权限问题、浏览器设置、代码错误或者平台兼容性等。我需要逐一考虑这些可能性。 权限问题是最常见的。用户可能没有允许浏览器访问摄像头,或者Unity的WebGL构建在请求权限时出现问题。需要检查浏览器的权限设置,并确保在安全上下文(HTTPS或localhost)下运行。 然后是代码问题。用户是否正确初始化了WebCamTexture?有没有错误处理?是否在正确的生命周期方法中启动摄像头?可能需要检查代码逻辑,比如是否在Start或Awake中调用Play(),是否有正确处理设备访问失败的情况。 平台兼容性也是一个重要因素。不同的浏览器对WebRTC的支持不同,特别是移动端浏览器可能有更多限制。比如iOS上的Safari可能需要用户手势才能触发摄像头访问,或者某些浏览器不支持特定的分辨率设置。 另外,Unity的WebGL导出设置是否正确?是否启用了必要的API或插件?比如,可能需要检查Player Settings中的WebGL设置,确保没有禁用摄像头相关的功能。 还有可能是硬件问题,比如摄像头被其他应用占用,或者驱动有问题。但用户是开发者,可能已经排除了这些,但也不能完全忽略。 接下来,我需要组织这些可能性,并为每个问题提供具体的解决步骤。例如: 1. 检查浏览器权限:确保用户已经允许访问摄像头,并且页面是通过HTTPS或localhost加载的。 2. 验证代码逻辑:确认WebCamTexture是否正确初始化,是否有错误处理,是否在用户交互后触发摄像头访问(如点击事件)。 3. 处理浏览器兼容性:针对不同浏览器进行测试,特别是移动端,可能需要调整代码或添加提示。 4. 检查Unity设置:确保WebGL导出设置正确,没有禁用相关功能,使用最新版本的Unity。 5. 调试和日志:使用浏览器开发者工具查看控制台输出,是否有错误信息,或者使用Unity的调试工具获取更多信息。 同时,用户可能需要具体的代码示例,比如如何在用户点击按钮后启动摄像头,如何处理权限被拒绝的情况,或者如何通过JavaScript插件与Unity交互来解决某些兼容性问题。 还需要考虑用户的技术水平,他们可能对Unity和WebGL有一定了解,但遇到具体问题时需要详细的步骤指导。可能需要分步骤解释,并提供代码片段和配置建议。 最后,要确保回答结构清晰,便于用户逐步排查问题,同时给出预防措施,比如推荐使用HTTPS,处理用户拒绝权限的情况,以及测试不同浏览器的建议。</think>在 Unity使用 `WebCamTexture` 开发时,若客户端无法调取摄像头,可能是由以下原因导致。以下是详细的排查步骤和解决方案: --- ### **1. 浏览器权限未授权** #### **现象**: - 浏览器未弹出摄像头权限请求弹窗,或用户未点击“允许”。 - 控制台报错 `NotAllowedError` 或 `Permission denied`。 #### **解决方案**: 1. **确保通过 HTTPS 或 localhost 运行**: 浏览器要求摄像头必须在安全上下文(HTTPS 或 localhost)中调用。若通过 `file://` 协议打开页面,摄像头会被直接禁用。 - 本地测试时使用 `http://localhost`。 - 线上部署时需配置 HTTPS。 2. **主动触发权限请求**: 浏览器要求 **用户主动交互**(如点击按钮)后才能申请摄像头权限。直接通过 `Start()` 调用可能被拦截。 ```csharp // Unity C# 示例:通过按钮点击触发摄像头 public class CameraController : MonoBehaviour { private WebCamTexture webcamTexture; public void OnCameraButtonClick() { if (webcamTexture == null) { webcamTexture = new WebCamTexture(); GetComponent<Renderer>().material.mainTexture = webcamTexture; webcamTexture.Play(); } } } ``` --- ### **2. 代码逻辑问题** #### **现象**: - 摄像头画面黑屏、无反应,或 Unity 报错 `WebCamTexture device is not available`。 #### **解决方案**: 1. **检查设备是否存在**: 在调用 `WebCamTexture.Play()` 前,确认设备列表中有摄像头。 ```csharp if (WebCamTexture.devices.Length == 0) { Debug.LogError("未检测到摄像头设备!"); return; } webcamTexture = new WebCamTexture(WebCamTexture.devices[0].name); // 指定设备名称 ``` 2. **处理异步启动延迟**: 部分浏览器需要时间初始化摄像头,添加延迟逻辑或等待回调。 ```csharp IEnumerator StartCamera() { webcamTexture = new WebCamTexture(); webcamTexture.Play(); yield return new WaitUntil(() => webcamTexture.width > 100); // 等待摄像头画面就绪 // 更新材质或UI } ``` --- ### **3. 浏览器兼容性问题** #### **现象**: - 在 iOS Safari 或某些移动端浏览器中失效。 - 控制台报错 `navigator.mediaDevices is undefined`。 #### **解决方案**: 1. **针对 iOS Safari 的特殊处理**: iOS 要求必须在 **用户手势事件**(如 `touchend`)中触发摄像头调用,且需通过 `<button>` 元素而非 Unity UI 按钮。 - 在 HTML 模板中添加原生按钮,通过 JavaScript 与 Unity 通信: ```html <!-- 在 Unity WebGL 模板的 HTML 中 --> <button id="cameraButton" onclick="UnityInstance.SendMessage('GameObject', 'OnCameraButtonClick')">启用摄像头</button> ``` 2. **兼容性代码补丁**: 某些浏览器不支持 `WebCamTexture` 的自动适配,需通过 JavaScript 插件强制指定参数: ```javascript // 在 Unity 项目的 Plugins/WebGL 目录下添加 camera-patch.jslib mergeInto(LibraryManager.library, { RequestCamera: function() { navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" } }) // 强制使用前置摄像头 .then(stream => { /* 处理成功 */ }) .catch(error => { /* 处理失败 */ }); } }); ``` --- ### **4. Unity 配置或环境问题** #### **现象**: - WebGL 打包后完全无响应,或报错 `WebGLPlayer is not supported`。 #### **解决方案**: 1. **检查 Unity 版本**: 使用 **Unity 2019.4+** 或更新的 LTS 版本,旧版本可能存在 WebGL 兼容性问题。 2. **修改 WebGL 编译选项**: 在 `Player Settings > WebGL > Publishing Settings` 中: - 启用 **Enable Exceptions**(Full Without Stacktrace)。 - 禁用 **Strip Engine Code**(防止关键代码被裁剪)。 --- ### **5. 调试与日志** #### **关键步骤**: 1. **浏览器开发者工具**: - 按 `F12` 打开控制台,查看是否有 JavaScript 错误或 C# 异常。 - 在 `Network` 面板确认所有 Unity WebGL 文件加载成功。 2. **Unity 调试输出**: 在代码中添加 `Debug.Log`,跟踪摄像头状态: ```csharp Debug.Log($"摄像头状态: {webcamTexture?.isPlaying}"); Debug.Log($"设备列表: {string.Join(", ", WebCamTexture.devices.Select(d => d.name))}"); ``` --- ### **总结** 若 Unity 的 `WebCamTexture` 无法调用摄像头,按以下优先级排查: 1. **权限与安全上下文** → 2. **用户交互触发** → 3. **设备与代码逻辑** → 4. **浏览器兼容性补丁** → 5. **Unity 配置与调试**。 通过分步骤验证,可快速定位问题根源。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值