RawImage and WebCam Texture doesnt works: Android Camera App

I’m creating a Unity project for Android mobile devices, similar to a “Instagram/Snapchat” Camera filter app but dedicated for my work, so we can create photos and videos with our own dedicated and private filters.

In the Hierarchy of the project, I have the following elements:

+Main Camera
+Canvas:

  • RawImage
  • CaptureButton
  • FlashButton
  • FilterDropdown
  • FilterButton
  • RecordButton
  • StopButton
  • CameraController
  • PreviewPanel
  • FilterManager

The problem is that Im creating this project from basic notions of programming and Unity, and I have 3 scripts in my project:

CameraController.cs

using UnityEngine;
using System;
using NativeGalleryNamespace;
using UnityEngine.UI;
using UnityEngine.UIElements;

public class CameraController : MonoBehaviour
{
    private WebCamTexture webCamTexture;
    private Texture2D currentPhoto;
    private string recordedVideoPath;
    public RawImage cameraPreview;
    public PreviewController previewController;

    private bool isRecording = false;

    public void StartCamera()
    {
        if (!Application.HasUserAuthorization(UserAuthorization.WebCam))
        {
            Application.RequestUserAuthorization(UserAuthorization.WebCam);
        }

        if (webCamTexture == null)
        {
            webCamTexture = new WebCamTexture(1080, 1920, 30);
            cameraPreview.texture = webCamTexture;
            webCamTexture.Play();
            DebugLogger.Log("Cámara inicializada correctamente.");
        }

        else if (!webCamTexture.isPlaying)
        {
            webCamTexture.Play();
            DebugLogger.Log("Reanudando cámara.");
        }
    }

    public void StopCamera()
    {
        if (webCamTexture != null && webCamTexture.isPlaying) 
        {
            webCamTexture.Stop();
            DebugLogger.Log("Cámara detenida.");
        }
    }

    public void CapturePhoto(Action<Texture2D> onPhotoCaptured)
    {
        if (webCamTexture != null && webCamTexture.isPlaying)
        {
            currentPhoto = new Texture2D(webCamTexture.width, webCamTexture.height);
            currentPhoto.SetPixels(webCamTexture.GetPixels());
            currentPhoto.Apply();
            onPhotoCaptured?.Invoke(currentPhoto);
            DebugLogger.Log("Foto capturada.");
        }
        else
        {
            Debug.LogWarning("No se puede capturar la foto, la cámara no está activa.");
        }
    }

    public void StartRecording()
    {
        Debug.Log("Grabación iniciada.");
        isRecording = true;
    }

    public void StopRecording(Action<string> onVideoStopped)
    {
        if (isRecording)
        {
            isRecording = false;
            Debug.Log("Grabación detenida.");

            // Lógica para guardar el video si es necesario
            recordedVideoPath = "/path/to/simulated/video.mp4";
            onVideoStopped?.Invoke(recordedVideoPath);
        }
        else
        {
            Debug.LogWarning("No se está grabando.");
        }
    }


    public void SavePhotoToDefaultPath(Action<bool> onComplete)
    {
        if (currentPhoto != null)
        {
            NativeGallery.SaveImageToGallery(currentPhoto, "MyAppGallery", "Photo_{0}.png", (success, path) =>
            {
                if (success)
                {
                    Debug.Log("Foto guardada en la ruta predeterminada: " + path);
                    onComplete?.Invoke(success);
                }
                else
                {
                    Debug.LogError("Error al guardar la foto en la ruta predeterminada.");
                    onComplete?.Invoke(false);
                }
            });
        }
        else
        {
            Debug.LogWarning("No hay foto para guardar.");
            onComplete?.Invoke(false);
        }
    }

    public void SavePhotoToCustomPath(Action<bool> onComplete)
    {
        if (currentPhoto != null)
        {
            NativeGallery.Permission permission = NativeGallery.RequestPermission(NativeGallery.PermissionType.Write, NativeGallery.MediaType.Image);

            if (permission == NativeGallery.Permission.Granted)
            {
                NativeGallery.SaveImageToGallery(currentPhoto, "MyAppGallery", "CustomPhoto_{0}.png", (success, path) =>
                {
                    if (success)
                    {
                        Debug.Log("Foto guardada correctamente en la galería: " + path);
                        onComplete?.Invoke(true);
                    }
                    else
                    {
                        Debug.LogError("Error al guardar en la galería.");
                        onComplete?.Invoke(false);
                    }
                });
            }
            else
            {
                Debug.LogError("Permiso denegado para guardar archivos.");
                onComplete?.Invoke(false);
            }
        }
        else
        {
            Debug.LogWarning("No hay foto para guardar.");
            onComplete?.Invoke(false);
        }
    }
}

PreviewController.cs

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;

public class PreviewController : MonoBehaviour
{
    public GameObject previewPanel;    
    public RawImage previewImage;      
    public VideoPlayer videoPlayer;    
    public CameraController cameraController;

    public void ShowPhotoPreview(Texture2D photo)
    {
        previewPanel.SetActive(true);
        videoPlayer.Stop();
        videoPlayer.gameObject.SetActive(false);

        previewImage.texture = photo;
        previewImage.gameObject.SetActive(true);
    }

    public void ShowVideoPreview(string videoPath)
    {
        previewPanel.SetActive(true);
        previewImage.gameObject.SetActive(false);

        videoPlayer.url = videoPath;
        videoPlayer.gameObject.SetActive(true);
        videoPlayer.Play();

        videoPlayer.loopPointReached += OnVideoEnd;
    }

    private void OnVideoEnd(VideoPlayer vp)
    {
        videoPlayer.Stop();
        Debug.Log("El video ha terminado.");
    }

    public void OnConfirmButtonPressed()
    {
        previewPanel.SetActive(false);
        videoPlayer.Stop();
        cameraController.StartCamera();
    }

    public void OnCancelButtonPressed()
    {
        previewPanel.SetActive(false);
        videoPlayer.Stop();
        cameraController.StartCamera();
    }
}

UIController.cs

using UnityEngine;
using UnityEngine.UI;

public class UIController : MonoBehaviour
{
    public Button captureButton;
    public Button recordButton;
    public Button stopButton;
    public Button saveDefaultPathButton;
    public Button chooseSavePathButton;
    public CameraController cameraController;
    public PreviewController previewController;

    private void Start()
    {
        captureButton.onClick.AddListener(OnCaptureButtonClicked);
        recordButton.onClick.AddListener(OnRecordButtonClicked);
        stopButton.onClick.AddListener(OnStopButtonClicked);
        saveDefaultPathButton.onClick.AddListener(OnSaveDefaultPathButtonClicked);
        chooseSavePathButton.onClick.AddListener(OnChooseSavePathButtonClicked);

        stopButton.interactable = false;
    }

    public void OnCaptureButtonClicked()
    {
        cameraController.CapturePhoto(previewController.ShowPhotoPreview);
    }

    public void OnRecordButtonClicked()
    {
        cameraController.StartRecording();
        recordButton.interactable = false;
        stopButton.interactable = true;
    }

    public void OnStopButtonClicked()
    {
        cameraController.StopRecording(previewController.ShowVideoPreview);
        recordButton.interactable = true;
        stopButton.interactable = false;
    }

    public void OnSaveDefaultPathButtonClicked()
    {
        cameraController.SavePhotoToDefaultPath(success =>
        {
            Debug.Log(success ? "Foto guardada correctamente." : "Error al guardar la foto.");
        });
    }

    public void OnChooseSavePathButtonClicked()
    {
        cameraController.SavePhotoToCustomPath(success =>
        {
            Debug.Log(success ? "Foto guardada en la ruta seleccionada." : "Error al guardar en la ruta.");
        });
    }
}

Canvas has attached the components:

  • “UI Controller (Script)” (with Capture Button, Record Button, Stop Button, Save Default Path Button, Choose Sabe Path Button, Camera Controller and Preview Controller)
  • and “Preview Controller (Script)” (Preview Panel, Preview Image, Video Player and Camera Controller)

Now, the problem is that, even if I try to build the scene in my Unity Project or my Android device, the RawImage doesnt works and the Camera doesnt starts.

Also, I have installed NativeCamera into the project to make sure all the Android Camera permissions works perfectly.

Am I doing something wrong? Also, If you see anything bad written or configured in this scripts or you need to check anything of my project, please leave a comment or message.

Thanks for your help! <3

I would begin your investigation with the device logs, available via adb logcat. Using mobile hardware often requires several different steps of configuration and missing even one of them will prevent successful operation.

Sounds like you wrote a bug… and that means… time to start debugging!

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.

I’ve tried using ADB and a lot debugging and the most simple thing, taking a picture, doesnt works.

I remade my project only to test WebCamTexture and TakePhoto to my device. How can I share my project here so anyone could help me?