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. Dismiss Notice

In game screenshot

Discussion in 'Editor & General Support' started by ykswobel, Mar 11, 2020.

  1. ykswobel

    ykswobel

    Joined:
    Apr 5, 2018
    Posts:
    57
    Hi All,

    I've found a script which i was actually brainly able to use and more or less understand.

    Main problem, the taken screenshot does not included the UI with canevas and image.
    May be someone has a clue why?

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.IO;
    4. // Screen Recorder will save individual images of active scene in any resolution and of a specific image format
    5. // including raw, jpg, png, and ppm.  Raw and PPM are the fastest image formats for saving.
    6. //
    7. // You can compile these images into a video using ffmpeg:
    8. // ffmpeg -i screen_3840x2160_%d.ppm -y test.avi
    9. public class ScreenRecorder : MonoBehaviour
    10. {
    11.      // 4k = 3840 x 2160   1080p = 1920 x 1080
    12.      public int captureWidth = 1920;
    13.      public int captureHeight = 1080;
    14.      // optional game object to hide during screenshots (usually your scene canvas hud)
    15.      public GameObject hideGameObject;
    16.      // optimize for many screenshots will not destroy any objects so future screenshots will be fast
    17.      public bool optimizeForManyScreenshots = true;
    18.      // configure with raw, jpg, png, or ppm (simple raw format)
    19.      public enum Format { RAW, JPG, PNG, PPM };
    20.      public Format format = Format.PPM;
    21.      // folder to write output (defaults to data path)
    22.      public string folder;
    23.      // private vars for screenshot
    24.      private Rect rect;
    25.      private RenderTexture renderTexture;
    26.      private Texture2D screenShot;
    27.      private int counter = 0; // image #
    28.      // commands
    29.      private bool captureScreenshot = false;
    30.      private bool captureVideo = false;
    31.      // create a unique filename using a one-up variable
    32.      private string uniqueFilename(int width, int height)
    33.      {
    34.          // if folder not specified by now use a good default
    35.          if (folder == null || folder.Length == 0)
    36.          {
    37.              folder = Application.dataPath;
    38.              if (Application.isEditor)
    39.              {
    40.                  // put screenshots in folder above asset path so unity doesn't index the files
    41.                  var stringPath = folder + "/..";
    42.                  folder = Path.GetFullPath(stringPath);
    43.              }
    44.              folder += "/screenshots";
    45.              // make sure directoroy exists
    46.              System.IO.Directory.CreateDirectory(folder);
    47.              // count number of files of specified format in folder
    48.              string mask = string.Format("screen_{0}x{1}*.{2}", width, height, format.ToString().ToLower());
    49.              counter = Directory.GetFiles(folder, mask, SearchOption.TopDirectoryOnly).Length;
    50.          }
    51.          // use width, height, and counter for unique file name
    52.          var filename = string.Format("{0}/screen_{1}x{2}_{3}.{4}", folder, width, height, counter, format.ToString().ToLower());
    53.          // up counter for next call
    54.          ++counter;
    55.          // return unique filename
    56.          return filename;
    57.      }
    58.      public void CaptureScreenshot()
    59.      {
    60.          captureScreenshot = true;
    61.      }
    62.      void Update()
    63.      {
    64.          // check keyboard 'k' for one time screenshot capture and holding down 'v' for continious screenshots
    65.          captureScreenshot |= Input.GetKeyDown("q");
    66.          captureVideo = Input.GetKey("v");
    67.          if (captureScreenshot || captureVideo)
    68.          {
    69.              captureScreenshot = false;
    70.              // hide optional game object if set
    71.              if (hideGameObject != null) hideGameObject.SetActive(false);
    72.              // create screenshot objects if needed
    73.              if (renderTexture == null)
    74.              {
    75.                  // creates off-screen render texture that can rendered into
    76.                  rect = new Rect(0, 0, captureWidth, captureHeight);
    77.                  renderTexture = new RenderTexture(captureWidth, captureHeight, 24);
    78.                  screenShot = new Texture2D(captureWidth, captureHeight, TextureFormat.RGB24, false);
    79.              }
    80.        
    81.              // get main camera and manually render scene into rt
    82.              Camera camera = this.GetComponent<Camera>(); // NOTE: added because there was no reference to camera in original script; must add this script to Camera
    83.              camera.targetTexture = renderTexture;
    84.              camera.Render();
    85.              // read pixels will read from the currently active render texture so make our offscreen
    86.              // render texture active and then read the pixels
    87.              RenderTexture.active = renderTexture;
    88.              screenShot.ReadPixels(rect, 0, 0);
    89.              // reset active camera texture and render texture
    90.              camera.targetTexture = null;
    91.              RenderTexture.active = null;
    92.              // get our unique filename
    93.              string filename = uniqueFilename((int) rect.width, (int) rect.height);
    94.              // pull in our file header/data bytes for the specified image format (has to be done from main thread)
    95.              byte[] fileHeader = null;
    96.              byte[] fileData = null;
    97.              if (format == Format.RAW)
    98.              {
    99.                  fileData = screenShot.GetRawTextureData();
    100.              }
    101.              else if (format == Format.PNG)
    102.              {
    103.                  fileData = screenShot.EncodeToPNG();
    104.              }
    105.              else if (format == Format.JPG)
    106.              {
    107.                  fileData = screenShot.EncodeToJPG();
    108.              }
    109.              else // ppm
    110.              {
    111.                  // create a file header for ppm formatted file
    112.                  string headerStr = string.Format("P6\n{0} {1}\n255\n", rect.width, rect.height);
    113.                  fileHeader = System.Text.Encoding.ASCII.GetBytes(headerStr);
    114.                  fileData = screenShot.GetRawTextureData();
    115.              }
    116.              // create new thread to save the image to file (only operation that can be done in background)
    117.              new System.Threading.Thread(() =>
    118.              {
    119.                  // create file and write optional header with image bytes
    120.                  var f = System.IO.File.Create(filename);
    121.                  if (fileHeader != null) f.Write(fileHeader, 0, fileHeader.Length);
    122.                  f.Write(fileData, 0, fileData.Length);
    123.                  f.Close();
    124.                  Debug.Log(string.Format("Wrote screenshot {0} of size {1}", filename, fileData.Length));
    125.              }).Start();
    126.              // unhide optional game object if set
    127.              if (hideGameObject != null) hideGameObject.SetActive(true);
    128.              // cleanup if needed
    129.              if (optimizeForManyScreenshots == false)
    130.              {
    131.                  Destroy(renderTexture);
    132.                  renderTexture = null;
    133.                  screenShot = null;
    134.              }
    135.          }
    136.      }
    137. }
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,355
    I think if your Gui Canvas render mode is set to "screen space - overlay", then the GUI is not rendered by the camera, but actually drawn on to the screen afterward. This would mean that the canvas wouldn't render to the RenderTexture. You might have to set the render mode on the canvas to "screen space - camera".
     
  3. ykswobel

    ykswobel

    Joined:
    Apr 5, 2018
    Posts:
    57
    Hi,
    thanks for your reply!!, it actually works but the UI is now included in the post process effects :)
    i'll keep searching.
     
  4. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,355
    You maybe could do a two camera set-up where one camera renders the scene with post effects, and then you use a second camera to render the gui without clearing the first camera. Then I suppose the second camera could be the one that renders the screenshot.
     
  5. ykswobel

    ykswobel

    Joined:
    Apr 5, 2018
    Posts:
    57
    thanks for feedback. I'll check this asap.
     
  6. astaikos316

    astaikos316

    Joined:
    Apr 26, 2020
    Posts:
    2
    When I try to write files out as PPM using the above script, the resultant PPM image when viewing it in GIMP is upside down and mirrored. Can anyone tell me how to fix this?
     
  7. BBIT-SOLUTIONS

    BBIT-SOLUTIONS

    Joined:
    Feb 21, 2013
    Posts:
    38
    Having the same problem. It seems only to behave so inside Unity Editor. On android device everything looks correctly. It's very strange.