Unity 手机拍照以及相关问题

说明:用的5.6 所以也就是不可能有webplayer,以下都是在android手机上测试~

一:用Unity 自带WebCamTexture实现拍照功能

    1:首先搭建一个简易场景

                一个button按下  打开相机

                

           相机中有切换摄像头按钮 拍照按钮 预览图 

                

  2:编码

            (1):这里说明下,我看了很多帖子,都是说要先请求授权,然后当授权成功之后在打开摄像机,我在这里试了很多次,其实不用如此麻烦,比如你像下面这么写

public IEnumerator start()  
    {  
        yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);  
        if (Application.HasUserAuthorization(UserAuthorization.WebCam))  
        {  
            WebCamDevice[] devices = WebCamTexture.devices;  
            deviceName= devices[0].name;  
            tex=new WebCamTexture(deviceName,300,300,12);  
            tex.Play();  
        }  
    }  
其实没有必要,这两句其实没有啥效果,第二行代码不管怎么样都是true
Application.RequestUserAuthorization(UserAuthorization.WebCam); 
Application.HasUserAuthorization(UserAuthorization.WebCam)

这是官方文档上面的说明,如果不信,你可以把上面的代码tex.play(),注释,此时发布安装 根本不会有任何弹框显示是否要你授权,      或者你把前面的两句注释,也会显示授权,真正的授权就是摄像机play()

    

    可以自己试试,建议每次安装的时候卸载前一次的安装,或者改下包名

  (2):PC和手机上的不同点

        在pc上面,用来显示摄像头拍摄的照片photoImg,不用做任何改变

        

    但是这样发布到手机上发现是歪了90度,这个时候要调节下。

        

当我们按下“切换”按钮的时候会发现图片反了,这个时候要在图片切换的地方添加一句旋转函数

       photoImage.transform.Rotate(new Vector3(180, 0, 180));

这一点很麻烦,所以用来渲染相机拍到的photoImg最好是个正方形,然后start方法时候判断当前平台是否是在手机上,如果是就旋转就是90度,然后再切换相机的时候不要添加旋转函数(下面代码没加(因为我的photoImg不是正方形),只是提供一种思路)

    (3):代码(注意在pc和手机差别)

        

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
//拍照
public class TakePhotos : MonoBehaviour
{
    public Button startPhotoBtn; //开始拍照
    public Button getPhotoBtn;    //拍照
    public Button changeBtn;    //切换相机
    public RawImage photoImage;    //相机画面
    public RawImage photoPreview;  //预览图

    private string photoPath;  //相机存贮位置

    private WebCamTexture webcam1, webcam2; //这里当作两个摄像机处理
    //   private bool isAndroid;
    void Start()
    {
        startPhotoBtn.onClick.AddListener(InitWebCam);
        getPhotoBtn.onClick.AddListener(GetPhoto);
        changeBtn.onClick.AddListener(ChangeCamera);
        //photoPath = Application.dataPath + "/Texture/";
        //if (!Directory.Exists(photoPath))
        //{ Directory.CreateDirectory(photoPath); }
    }

    private void InitWebCam()
    {
        WebCamDevice[] devices = WebCamTexture.devices;

        int webCamLength = devices.Length;
        if (webCamLength <= 0)
        {
            Debug.Log("没有获取摄像机设备");
            return;
        }
        else if (webCamLength == 1)
        {
            //所选相机可能不支持请求的参数指定的宽度,高度和帧速率。在这种情况下,将使用最接近的可用值
            //根据纹理图片拍摄大小
            Debug.Log("有一个摄像机设备");
            webcam1 = new WebCamTexture(WebCamTexture.devices[0].name,
                (int)photoImage.rectTransform.rect.width,
                (int)photoImage.rectTransform.rect.height, 12);
        }
        else if (webCamLength == 2)
        {
            Debug.Log("有两个摄像机设备");
            webcam1 = new WebCamTexture(WebCamTexture.devices[0].name,
           (int)photoImage.rectTransform.rect.width,
           (int)photoImage.rectTransform.rect.height, 12);
            webcam2 = new WebCamTexture(WebCamTexture.devices[1].name,
               (int)photoImage.rectTransform.rect.width,
               (int)photoImage.rectTransform.rect.height, 12);
        }
        if (webcam1 != null)  //当获取摄像机不为空
        {
            OpenWebCam1();
        }
    }

    /// <summary>
    /// 打开摄像头1
    /// </summary>
    private void OpenWebCam1()
    {
        //当webcam2不为空且在运行的时候
        if (webcam2 != null && webcam2.isPlaying)
        {
            webcam2.Stop();
        }
        webcam1.Play();
        photoImage.texture = webcam1;
    }
    /// <summary>
    /// 打开摄像头2
    /// </summary>
    private void OpenWebCam2()
    {
        if (webcam1 != null && webcam1.isPlaying)
        {
            webcam1.Stop();
        }
        webcam2.Play();
        photoImage.texture = webcam2;
    }
    /// <summary>
    /// 获取正在运行的摄像头
    /// </summary>
    /// <returns></returns>
    private WebCamTexture GetCurrentWebCam()
    {
        return webcam1.isPlaying ? webcam1 : webcam2;
    }
    /// <summary>
    /// 切换相机
    /// </summary>
    private void ChangeCamera()
    {
        //如果web2为空,即只有一个摄像头 返回
        if (webcam2 == null) return;
        //得到另一个相机
        WebCamTexture otherWebCam = GetCurrentWebCam() == webcam1 ? webcam2 : webcam1;
        if (otherWebCam == webcam1)
        {
            OpenWebCam1();
        }
        else
        {
            OpenWebCam2();
        }
        photoImage.transform.Rotate(new Vector3(180, 0, 180));
    }

    /// <summary>
    /// 拍照
    /// </summary>
    private void GetPhoto()
    {
        StartCoroutine(IEGetPhoto());
    }
    private IEnumerator IEGetPhoto()
    {
        //获取当前的摄像头
        WebCamTexture currentWebCam = GetCurrentWebCam();
        currentWebCam.Pause();
        //必须加上这一句yield return,不然没办法ReadPixels
        yield return new WaitForEndOfFrame();
        //根据photoImage   new一个texture2D
        Texture2D texture2D =
            new Texture2D((int)photoImage.rectTransform.rect.width, (int)photoImage.rectTransform.rect.height, TextureFormat.ARGB32, false);
        //读取像素
        texture2D.ReadPixels(new Rect(0, Screen.height - photoImage.rectTransform.rect.height, photoImage.rectTransform.rect.width, photoImage.rectTransform.rect.height), 0, 0, false);

        texture2D.Apply();

        yield return new WaitForEndOfFrame();
        photoPreview.texture = texture2D;  //预览图
        currentWebCam.Play();
        //IO写入
        //byte[] bs = texture2D.EncodeToPNG();
        // string name = DateTime.Now.ToString("yyyyMMdd_HHmmss")+".png";
        // File.WriteAllBytes(photoPath+name, bs);
    }

}

    上面注释的地方是在pc平台可以写入图片到磁盘中

在手机上拍摄写入到相册目前没有成功 按照网上的做法 连接 可行 但是不会立即出现在相册

所有可能还是要自己写插件来实现

    

Unity中实现安卓平台调用摄像头进行拍照的功能,通常可以通过使用Unity的**Native插件**或者调用**Android的Intent**来完成。以下是一个较为常见的实现方法,使用Android的Intent机制来调用系统相机进行拍照,并将照片保存到设备中。 ### 实现步骤 1. **创建Android Intent** 使用Unity的`AndroidJavaClass`和`AndroidJavaObject`来调用Android原生的相机功能。首先需要创建一个Intent来启动系统相机应用。 2. **处理拍照结果** 拍照完成后,系统会返回图片数据或者保存图片的URI,需要在Unity中处理返回的数据并将图片保存或显示。 3. **权限配置** 在`AndroidManifest.xml`中添加相机权限和写入外部存储的权限: ```xml <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 4. **代码实现** 以下是一个示例代码片段,用于调用安卓系统的相机进行拍照,并将照片保存到指定路径: ```csharp using UnityEngine; using System.Collections; using System.IO; public class CameraCapture : MonoBehaviour { private string imagePath; public void TakePhoto() { // 创建一个Intent来调用系统相机 AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent"); AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent"); intentObject.Call<AndroidJavaObject>("setAction", "android.media.action.IMAGE_CAPTURE"); // 启动相机应用 AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); currentActivity.Call("startActivityForResult", intentObject, 0); } // 处理 onActivityResult 回调 void OnActivityResult(int requestCode, int resultCode, AndroidJavaObject data) { if (requestCode == 0 && resultCode == -1) { // 获取拍照返回的图片数据 AndroidJavaObject extras = data.Call<AndroidJavaObject>("getExtras"); AndroidJavaObject bitmap = extras.Call<AndroidJavaObject>("get", "data"); // 将Bitmap转换为字节数组并保存为PNG文件 byte[] imageData = bitmap.Call<byte[]>("compress", new object[] { "android.graphics.Bitmap$CompressFormat.PNG", 100, new MemoryStream() }); imagePath = Path.Combine(Application.persistentDataPath, "captured_photo.png"); File.WriteAllBytes(imagePath, imageData); Debug.Log("Photo saved to: " + imagePath); } } } ``` 5. **注意事项** - 由于Android 7.0(API 24)及以上版本对文件访问权限的限制,建议使用`FileProvider`来处理图片存储路径,避免出现`FileUriExposedException`异常。 - 在Unity的`Plugins/Android`目录中添加必要的Java代码或使用现成的插件(如Native Camera插件)可以简化开发流程。 - 如果需要更高级的功能(如自定义相机界面、实时图像处理),可以考虑使用Unity的**AR Foundation**或直接集成**Android Camera API**或**CameraX库**。 ### 权限请求(Android 6.0+) 在运行时请求权限以确保兼容性: ```csharp void RequestPermissions() { AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); string[] permissions = new string[] { "android.permission.CAMERA", "android.permission.WRITE_EXTERNAL_STORAGE" }; currentActivity.Call("requestPermissions", permissions, 1); } ``` ### 参考资料 - Unity官方文档中关于Android原生插件的开发指南[^1]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值