Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Screenshot from second camera with a render texture attached | How to?

Discussion in 'Scripting' started by Blckspawn92, Oct 19, 2023.

  1. Blckspawn92

    Blckspawn92

    Joined:
    Jul 19, 2023
    Posts:
    20
    I read through some documentation about render textures but I dont think im understanding it. Long and short of it, I want to take a screenshot of my secondary camera that has a render texture on it.

    From what ive gathered, I need to render the texture to another camera (a third?) and then screenshot it from there. This doesnt seem right to me.

    Below is the code I was using when it was being taken from my main camera. Would I be able to repurpose this or would I need to start over?

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class Screenshot : MonoBehaviour
    7. {
    8.     float Size = 1375;
    9.  
    10.     public void SaveDatasheet()
    11.     {
    12.             Camera.main.orthographicSize = Size;
    13.             Camera.main.transform.position = new Vector3(0, 0, 0);
    14.            
    15.             //ScreenCapture.CaptureScreenshot("Datasheet.png");
    16.             StartCoroutine(CoroutineScreenshot());
    17.     }
    18.  
    19.     private IEnumerator CoroutineScreenshot() {
    20.         yield return new WaitForEndOfFrame();
    21.  
    22.         int width = Screen.width;
    23.         int height = Screen.height;
    24.         Texture2D screenshotTexture = new Texture2D(width, height, TextureFormat.ARGB32, false);
    25.         Rect rect = new Rect(0, 0, width, height);
    26.         screenshotTexture.ReadPixels(rect, 0, 0);
    27.         screenshotTexture.Apply();
    28.  
    29.         byte[] byteArray = screenshotTexture.EncodeToPNG();
    30.  
    31.         int filenumber = 0;
    32.         string filepath = System.IO.Directory.GetCurrentDirectory() + "/Datasheets/Datasheet" + filenumber.ToString() + ".png";
    33.         int length = 300;
    34.         for (int i = 0; i < length; i++)
    35.         {
    36.             if (!System.IO.File.Exists(filepath))
    37.             {
    38.                 System.IO.File.WriteAllBytes(filepath, byteArray);
    39.                 Debug.Log("Datasheet Saved to: " + filepath);
    40.                 yield break;
    41.             }
    42.             filenumber++;
    43.             filepath = System.IO.Directory.GetCurrentDirectory() + "/Datasheets/Datasheet" + filenumber.ToString() + ".png";
    44.         }
    45.  
    46.         //System.IO.File.WriteAllBytes(Application.dataPath + "/Datasheet.png", byteArray);
    47.     }
    48.  
    49.  
    50. }
    51.  
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,310
    Why would you screenshot a texture? You already have the render texture attached to the camera with the contents that the camera renders. Just save that texture as an image and you got yourself a screenshot of that camera.

    Or am I missing something here?
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    37,150
    Should just work. First thing I suspect is that your file paths aren't what you think they are. Print them out!

    Generally use
    Application.persistentDataPath
    to write files in Unity.

    Also, try and just snapshot it onto another texture on another material right there in the game, just get the RenderTexture working. Here's a few random functioning example with source links in the comments in the video:



     
  4. Blckspawn92

    Blckspawn92

    Joined:
    Jul 19, 2023
    Posts:
    20
    I guess that makes sense. I'm still fairly new to script writing. How would I go about doing that?
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    37,150
    Are you just looking for
    ScreenCapture.CaptureScreenshot()
    ??? That's always the easiest...
     
  6. Blckspawn92

    Blckspawn92

    Joined:
    Jul 19, 2023
    Posts:
    20
    Would I be able to attach that to a camera that has the render texture on it?
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    37,150
    Go look at the docs. It's a static method. It snaps whatever your main game surface is doing. I have no idea what it does in a multi-monitor setup but it's trivial to test it.
     
  8. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    395
    Google search "Unity save RenderTexture to file". First result:
    https://forum.unity.com/threads/save-rendertexture-or-texture2d-as-image-file-utility.1325130/

    If you want to progress in any type of software development, you need to absolutely know how to Google (and in 2024 how to craft a ChatGPT prompt), it's a skill as important as learning how to program.
     
    Kurt-Dekker likes this.
  9. Blckspawn92

    Blckspawn92

    Joined:
    Jul 19, 2023
    Posts:
    20
    I managed to figure it out. I wasn't too far off and had to find a video from 2010 to fill in the gaps. Rendering the texture file messed me up a lot but once I figured that out I was able to cobble this together.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.IO;
    6. using TMPro.Examples;
    7.  
    8. public class GetImage : MonoBehaviour
    9. {
    10.     public RenderTexture RT;
    11.     public GameObject RenderCamera;
    12.  
    13.     public void SaveImage()
    14.     {
    15.         StartCoroutine(CoroutineScreenshot());      
    16.     }
    17.  
    18.  
    19.     private IEnumerator CoroutineScreenshot() {
    20.         yield return new WaitForEndOfFrame();
    21.  
    22.         Texture2D texture2D = new Texture2D(RT.width, RT.height, TextureFormat.ARGB32, false);
    23.         RenderTexture.active = RT;
    24.         texture2D.ReadPixels(new Rect(0,0, RT.width, RT.height), 0,0);
    25.         texture2D.Apply();
    26.  
    27.         byte[] byteArray = texture2D.EncodeToPNG();
    28.  
    29.         int filenumber = 0;
    30.         string filepath = System.IO.Directory.GetCurrentDirectory() + "/Datasheets/Datasheet" + filenumber.ToString() + ".png";
    31.         int length = 300;
    32.         for (int i = 0; i < length; i++)
    33.         {
    34.             if (!System.IO.File.Exists(filepath))
    35.             {
    36.                 System.IO.File.WriteAllBytes(filepath, byteArray);
    37.                 Debug.Log("Datasheet Saved to: " + filepath);
    38.                 yield break;
    39.             }
    40.             filenumber++;
    41.             filepath = System.IO.Directory.GetCurrentDirectory() + "/Datasheets/Datasheet" + filenumber.ToString() + ".png";
    42.         }
    43.     }
    44.  
    45. }
    The image is saved with the name "datasheet (0-300)" depending on how many are in the root folder.

    Thanks for the help everyone!

    EDIT: For anyone looking at this in the future, I attached the script to the render camera, then inserted the render texture and the render camera into the script. Then went to the button and did the "on-click" thing to the public void SaveImage() to take the screenshot.