Texture2D.ReadPixels Being Set But Not Saved?

Hello everyone and thanks in advance for any help given here.

Basically i added to the: Texture2D.ReadPixels

What i am trying to do is save the cameras view to a RawImage UI component and allow it to be saved on that RawImage so that when i load the games playerprefs, that image is still there and they can choose what save they want to load. A similar reference is the way skyrim presents saves in the form of images of the scene view.

I was also thinking of trying an alternative maybe creating a screenshot using Application.Screenshot i think is what it is and then setting that saved file to the RawImage or just directly to a sprite? Just a thought.

Here is what i have working:

-Load & Save system
-Setting the RawImage to the scene view

Here is whats not working:

-Playing the scene again in the editor a second time removes the Texture from the RawImage

Here is my script:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using plyBloxKit;

// Here we make sure you added the required components to this camera,
// if not, we will add them for you when you attach the script.
// WARNING: Be sure to place this on a camera.
[RequireComponent (typeof (Camera))]
[RequireComponent (typeof (plyBlox))]

public class ScreenGrab : MonoBehaviour {
 
   // This variable will present our bool that will be called when the
   // player saves the game so that we can grab a camera snapshot and
   // run our events.
  public bool setImage = true;
 
   // This variable holds the object with the blox component on it
   // and will fire a custom state when the player saves the game.
   public plyBlox bloxLogic;
 
   // This variable is the number that will be set on the script so that it can decide
   // which slot image to save to. The values by default range from 1-3 with 0 being null.
   public static int saveSlotNumber = 0;
 
   // OPTIONAL: Uncomment the variable line below if you want to be able to see the slot number change
   // while inside the inspector. Be sure to comment the above variable out if you want this one active.
   //public int saveSlotNumber;
 
   // These variables hold our save game slot images. Each one correlates
   // to its respective slot to be called in our events below. To add more
   // slots, simply copy and paste the whole variable line and change the
   // variable name to a unique name like shown below.
  public RawImage saveSlotOneImage;
   public RawImage saveSlotTwoImage;
   public RawImage saveSlotThreeImage;
 
   // OPTIONAL: These variables will serve as optional offsets that you can apply to
   // the screen capture ranging from any value in the X or Y axis.
   public float imagePosXOffset = 0;
   public float imagePosYOffset = 0;
 
   // These variables will capture the cameras view in accordance to the end users actual screen width
   // and size.
   private int grabWidthResolution = Screen.width;
   private int grabHeightResolution = Screen.height;
 
   // This function will be called from the camera after regular rendering is done.
  void OnPostRender() {
 
   // Here we will first check if our bool is True, if so, capture the scene view and save it to a texture
   // in accordance to the variables we have set in the inspector, excluding the getResolution variables.
  if (setImage) {
  Texture2D tex = new Texture2D(grabWidthResolution, grabHeightResolution);
  tex.ReadPixels(new Rect(imagePosXOffset, imagePosYOffset, grabWidthResolution, grabHeightResolution), 0, 0);
  tex.Apply();
     
       // Here check if the slot we want to save to is the correct slot and if so,
       // we will set our save slot image to our newly captured screen view.
       if (saveSlotNumber == 1) {
       saveSlotOneImage.texture = (Texture)tex;
       Debug.Log("Save Slot One Was Set");
       }
     
       // Here check if the slot we want to save to is the correct slot and if so,
       // we will set our save slot image to our newly captured screen view.
       if (saveSlotNumber == 2) {
       saveSlotTwoImage.texture = (Texture)tex;
       Debug.Log("Save Slot Two Was Set");
       }
     
       // Here check if the slot we want to save to is the correct slot and if so,
       // we will set our save slot image to our newly captured screen view.
       if (saveSlotNumber == 3) {
       saveSlotThreeImage.texture = (Texture)tex;
       Debug.Log("Save Slot Three Was Set");
       }
     
       // Here we will call an event from the plyBlox gameobject we specified in
       // the inspector. To change the events name that will be called, edit the
       // string after "blox.RunEvent".
       plyBlox blox = bloxLogic.GetComponent<plyBlox>();
       blox.RunEvent ("Test");
     
       // Here we finish our screen capture logic and turn the fuction off so that
       // it can be called again.
  setImage = false;
  }
  }
}

alt text

Hardly anything persists when exiting play mode, except for material property changes and maybe a few other things. So it’s expected that your textures being created in play mode are getting disposed.

To do something like this, you’re going to have to actually save the image data somewhere, most likely to a file. When starting up the game, you’ll have to load these files, if they exist, and supply the RawImage components with them after loading.

A small example:

using System.IO;

string filePath = Application.dataPath + "/save1.png";

void Load()
{
    if(File.Exists(filePath))
    {
        //Remember to save and load at the same resolution
        Texture2D tex = new Texture2D(512, 512);
        tex.LoadImage(File.ReadAllBytes(filePath))
        saveSlotOneImage.texture = tex;
    }
}

void Save()
{
    //Same texture creation you already have
    File.WriteAllBytes(filePath, tex.EncodeToPng());
}

Using Application.CaptureScreenshot is probably not good in this case, since players with different resolutions will output different size images. It’s probably best to keep a constant resolution for the save images.