Search Unity

How to save manually save a PNG of a camera view

Discussion in 'Scripting' started by wileyjerkins, Nov 26, 2017.

  1. wileyjerkins

    wileyjerkins

    Joined:
    Oct 13, 2017
    Posts:
    35
    Someone may find this useful. I looked for something similar and ran into all kinds of problems, so thought I would share my eventual solution.

    If you attach this script to any camera that has a valid target texture in its settings, it will save a PNG of that snapshot to your hard drive (note the folder name in my path) ... which you can later use for whatever purpose. I have this script attached to a camera that only renders the game background, and I use the images later to create randomized backgrounds.

    This demo script uses the F9 key to capture the image, but you can make it automatically capture at random times (start of each level or some other time when there's no action) if you wish.

    Code (CSharp):
    1. using System.IO;
    2. using UnityEngine;
    3.  
    4. public class SR_RenderCamera : MonoBehaviour {
    5.  
    6.     public int FileCounter = 0;
    7.  
    8.     private void LateUpdate()
    9.     {
    10.         if (Input.GetKeyDown(KeyCode.F9))
    11.         {
    12.             CamCapture();  
    13.         }
    14.     }
    15.  
    16.     void CamCapture()
    17.     {
    18.         Camera Cam = GetComponent<Camera>();
    19.  
    20.         RenderTexture currentRT = RenderTexture.active;
    21.         RenderTexture.active = Cam.targetTexture;
    22.  
    23.         Cam.Render();
    24.  
    25.         Texture2D Image = new Texture2D(Cam.targetTexture.width, Cam.targetTexture.height);
    26.         Image.ReadPixels(new Rect(0, 0, Cam.targetTexture.width, Cam.targetTexture.height), 0, 0);
    27.         Image.Apply();
    28.         RenderTexture.active = currentRT;
    29.  
    30.         var Bytes = Image.EncodeToPNG();
    31.         Destroy(Image);
    32.  
    33.         File.WriteAllBytes(Application.dataPath + "/Backgrounds/" + FileCounter + ".png", Bytes);
    34.         FileCounter++;
    35.     }
    36.    
    37. }
     
    ElnuDev, APSchmidt, unitylepi and 3 others like this.
  2. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    16
    Nice, thanks!
     
  3. APSchmidt

    APSchmidt

    Joined:
    Aug 8, 2016
    Posts:
    3,344
    ElnuDev likes this.
  4. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    284
    Thanks so much for this script! I can confirm it works in Unity 2019.3.0f6. I've made some performance, ease of use, and convention improvements to the script:

    Code (CSharp):
    1. using System.IO;
    2. using UnityEngine;
    3.  
    4. public class CameraCapture : MonoBehaviour
    5. {
    6.     public int fileCounter;
    7.     public KeyCode screenshotKey;
    8.     private Camera Camera
    9.     {
    10.         get
    11.         {
    12.             if (!_camera)
    13.             {
    14.                 _camera = Camera.main;
    15.             }
    16.             return _camera;
    17.         }
    18.     }
    19.     private Camera _camera;
    20.  
    21.     private void LateUpdate()
    22.     {
    23.         if (Input.GetKeyDown(screenshotKey))
    24.         {
    25.             Capture();
    26.         }
    27.     }
    28.  
    29.     public void Capture()
    30.     {
    31.         RenderTexture activeRenderTexture = RenderTexture.active;
    32.         RenderTexture.active = Camera.targetTexture;
    33.  
    34.         Camera.Render();
    35.  
    36.         Texture2D image = new Texture2D(Camera.targetTexture.width, Camera.targetTexture.height);
    37.         image.ReadPixels(new Rect(0, 0, Camera.targetTexture.width, Camera.targetTexture.height), 0, 0);
    38.         image.Apply();
    39.         RenderTexture.active = activeRenderTexture;
    40.  
    41.         byte[] bytes = image.EncodeToPNG();
    42.         Destroy(image);
    43.  
    44.         File.WriteAllBytes(Application.dataPath + "/Backgrounds/" + fileCounter + ".png", bytes);
    45.         fileCounter++;
    46.     }
    47. }
    Let me know if you have any problems with it! Again, big thanks to @wileyjerkins for making the original script! :D
     
    wileyjerkins likes this.
  5. wileyjerkins

    wileyjerkins

    Joined:
    Oct 13, 2017
    Posts:
    35
    I am stealing these improvements! Good job!
     
    ElnuDev likes this.
  6. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    284
    Thanks! Keep in mind that like the original, it unfortunately doesn't have any way to render gizmos since it is still using a render texture. Any ideas regarding taking a screenshot with gizmos?
     
  7. wileyjerkins

    wileyjerkins

    Joined:
    Oct 13, 2017
    Posts:
    35
    That is a complicated thing. Essentially you have to create your own gizmos, but fortunately someone else has done it for you. https://github.com/popcron/gizmos
     
    ElnuDev likes this.
  8. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    284
    Neat! Can't wait to try it out. Too bad there isn't any setting to make vanilla gizmos render in the camera/builds, though. :(
     
unityunity