Unity 中的定位相機Locatable camera in Unity

啟用相片攝影機的功能Enabling the capability for Photo Video Camera

必須為應用程式宣告「網路攝影機」功能才能使用 相機The "WebCam" capability must be declared for an app to use the camera.

  1. 在 Unity 編輯器中,流覽至 [> Player 編輯 > 專案設定] 頁面,移至播放機設定In the Unity Editor, go to the player settings by navigating to the "Edit > Project Settings > Player" page
  2. 按一下 [Windows 存放區] 索引標籤Click the "Windows Store" tab
  3. 在 [發佈設定 > 功能] 區段中,檢查 網路 攝影機和 麥克風 功能In the "Publishing Settings > Capabilities" section, check the WebCam and Microphone capabilities

攝影機一次只能有一種操作。Only a single operation can occur with the camera at a time. 若要判斷 (相片、影片或無) 相機目前所在的模式,您可以檢查 UnityEngine. XR。To determine which mode (photo, video, or none) the camera is currently in, you can check UnityEngine.XR.WSA.WebCam.Mode.

相片捕獲Photo Capture

命名空間: UnityEngine. XRNamespace: UnityEngine.XR.WSA.WebCam
類型: PhotoCaptureType: PhotoCapture

PhotoCapture 型別可讓您以照片攝影機拍攝相片。The PhotoCapture type allows you to take still photographs with the Photo Video Camera. 使用 PhotoCapture 拍攝相片的一般模式如下:The general pattern for using PhotoCapture to take a photo is as follows:

  1. 建立 PhotoCapture 物件Create a PhotoCapture object
  2. 使用您想要的設定來建立 CameraParameters 物件Create a CameraParameters object with the settings you want
  3. 透過 StartPhotoModeAsync 啟動相片模式Start Photo Mode via StartPhotoModeAsync
  4. 取得所需的相片Take the desired photo
    • (選擇性) 與該圖片互動(optional) Interact with that picture
  5. 停止相片模式並清除資源Stop Photo Mode and clean up resources

PhotoCapture 的一般設定Common Set Up for PhotoCapture

針對這三種用途,請從上述的前3個步驟開始For all three uses, start with the same first 3 steps above

一開始先建立 PhotoCapture 物件Start by creating a PhotoCapture object

PhotoCapture photoCaptureObject = null;
   void Start()
   {
       PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
   }

接下來,儲存您的物件、設定您的參數和啟動相片模式Next, store your object, set your parameters, and start Photo Mode

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);
   }

最後,您也會使用此處所提供的相同清除程式碼In the end, you will also use the same clean up code presented here

void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
   {
       photoCaptureObject.Dispose();
       photoCaptureObject = null;
   }

在這些步驟之後,您可以選擇要捕獲的相片類型。After these steps, you can choose which type of photo to capture.

將相片拍攝至檔案Capture a Photo to a File

最簡單的操作是直接將相片捕獲到檔案。The simplest operation is to capture a photo directly to a file. 您可以將相片儲存為 JPG 或 PNG。The photo can be saved as a JPG or a PNG.

如果您已成功啟動相片模式,請拍攝相片,並將其儲存在磁片上If you successfully started photo mode, take a photo and store it on disk

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!");
       }
   }

將相片捕獲到磁片之後,結束相片模式,然後清除您的物件After capturing the photo to disk, exit photo mode and then clean up your objects

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");
       }
   }

將相片拍攝至 Texture2DCapture a Photo to a Texture2D

將資料捕獲到 Texture2D 時,此程式非常類似于捕捉至磁片。When capturing data to a Texture2D, the process is extremely similar to capturing to disk.

遵循上述的設定程式。Follow the set up process above.

OnPhotoModeStarted 中,將框架捕獲到記憶體。In OnPhotoModeStarted, capture a frame to memory.

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
   {
       if (result.success)
       {
           photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
       }
       else
       {
           Debug.LogError("Unable to start photo mode!");
       }
   }

然後,您會將結果套用至材質,並使用上述的一般清除程式碼。You will then apply your result to a texture and use the common clean up code above.

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);
   }

捕捉相片並與原始位元組互動Capture a Photo and Interact with the Raw bytes

若要與記憶體內框架中的原始位元組互動,請遵循上述相同的設定步驟,並 OnPhotoModeStarted 以將相片捕捉至 Texture2D。To interact with the raw bytes of an in memory frame, follow the same set up steps as above and OnPhotoModeStarted as in capturing a photo to a Texture2D. 差異是在 OnCapturedPhotoToMemory 中,您可以在其中取得原始位元組並與其互動。The difference is in OnCapturedPhotoToMemory where you can get the raw bytes and interact with them.

在此範例中,您將建立可透過 SetPixels 進一步處理或套用至材質的 清單 ( # B1In this example, you will create a List which could be further processed or applied to a texture via 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);
   }

影片捕獲Video Capture

命名空間: UnityEngine. XRNamespace: UnityEngine.XR.WSA.WebCam
類型: VideoCaptureType: VideoCapture

VideoCapture 函式與 PhotoCapture 的功能非常類似。VideoCapture functions very similarly to PhotoCapture. 唯一的兩個差異是您必須指定每秒的畫面格 (FPS) 值,而且您只能將磁片直接儲存為磁片磁碟機。The only two differences are that you must specify a Frames Per Second (FPS) value and you can only save directly to disk as an .mp4 file. 使用 VideoCapture 的步驟如下:The steps to use VideoCapture are as follows:

  1. 建立 VideoCapture 物件Create a VideoCapture object
  2. 使用您想要的設定來建立 CameraParameters 物件Create a CameraParameters object with the settings you want
  3. 透過 StartVideoModeAsync 啟動影片模式Start Video Mode via StartVideoModeAsync
  4. 開始錄製影片Start recording video
  5. 停止錄製影片Stop recording video
  6. 停止影片模式並清除資源Stop Video Mode and clean up resources

首先,建立我們的 VideoCapture 物件 VideoCapture m_VideoCapture = null;Start by creating our VideoCapture object VideoCapture m_VideoCapture = null;

void Start ()
   {
       VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
   }

接下來,設定您想要錄製和啟動的參數。Next, set up the parameters you will want for the recording and start.

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!");
       }
   }

啟動後,開始錄製Once started, begin the recording

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 或行為以啟用停止。After recording has started, you could update your UI or behaviors to enable stopping. 您只需記錄即可。Here you just log.

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.
   }

稍後,您會想要停止錄製。At a later point, you will want to stop the recording. 例如,計時器或使用者輸入可能會發生這種情況。This could happen from a timer or user input, for instance.

// The user has indicated to stop recording
   void StopRecordingVideo()
   {
       m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
   }

記錄停止後,請停止影片模式並清除您的資源。Once the recording has stopped, stop video mode and clean up your resources.

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;
   }

疑難排解Troubleshooting

  • 沒有任何可用的解決方案No resolutions are available
    • 確定您的專案中已指定 網路 攝影機功能。Ensure the WebCam capability is specified in your project.

下一個開發檢查點Next Development Checkpoint

如果您要遵循我們所配置的 Unity 開發檢查點旅程,您將會在探索混合現實平臺功能和 Api。If you're following the Unity development checkpoint journey we've laid out, you're in the midst of exploring the Mixed Reality platform capabilities and APIs. 接下來,您可以繼續進行下一個主題:From here, you can proceed to the next topic:

或者,直接跳到在裝置或模擬器上部署應用程式的主題:Or jump directly to deploying your app on a device or emulator:

您可以隨時回到 Unity 開發檢查點You can always go back to the Unity development checkpoints at any time.

另請參閱See Also

  • [定位相機Locatable camera](../platform-capab ilities-and-apis/locatable-camera.md)