I need help saving data from objects I create from script.

Hello , I’m making a Puzzle Slider game , where I create (with create primitive c# code) quads , and then I apply a texture and a script called Bloques and the puzzle size is determined by a variable , for example if I use 3 in the variable the puzzle will be 3X3, etc.
My problem is that I want to save the user progress of the game , that means the position of the quads.

Here’s an image to understand it better:

So I have a block that the user can’t see because is not active in the scene , but I use that block to move the ones that are active.

Each Quad has a script called Bloques , each Quad has a coordinate , its a public variable called coordinada and its a Vector2Int type.

My problem is that I don’t know how to save the state of the game (I mean it in a file), so if the user make’s progress in the puzzle , close the game , and start that level it will be from scratch what I want to do is save the user progress.

How could I save the “status” of the scene as data?
I’ve tried for a few days and I’m running crazy because I’m close to end the game.

Thank you in advance.

have a look at JSON saving data in the docs Beginner Scripting - Unity Learn

with this method you’re able to load and save complex scripts / manager, so i’d do a save manager class =>

public class SaveManager{
  public int currentscene;
  public PuzzleManager currenPuzzle;
  public PuzzleState //3/100 finished
  //can be more just for an idea
  }

@dan_wipf Thank you again for your answer!
This is the function that creates the puzzle:

public void crearPuzzle()
         {
             int contador = 0;
             this.bloques = new Bloque[this.bloquesPorLinea, this.bloquesPorLinea];
             Texture2D[,] array = CortaImagen.CortarImagen(this.imagen, this.bloquesPorLinea);
             for (int i = 0; i < this.bloquesPorLinea; i++)
             {
                 for (int j = 0; j < this.bloquesPorLinea; j++)
                 {
                     contador ++;
                     GameObject gameObject = GameObject.CreatePrimitive(PrimitiveType.Quad);
                     gameObject.transform.position = -Vector2.one * (float)(this.bloquesPorLinea - 1) * 0.5f + new Vector2((float)j, (float)i);
                     gameObject.name = "Quad" +contador;
                     gameObject.transform.parent = base.transform;
                     Bloque bloque = gameObject.AddComponent<Bloque>();
                     
                     bloque.OnBlockPressed += this.playerMueveBloque;
                     bloque.OnFinishMoving += this.OnFinishedMoving;
                     bloque.Init(new Vector2Int(j, i), array[j, i]); 
                     
                     gameObject.tag = "PiezasPuzzle";
                     this.bloques[j, i] = bloque;
                     
                     if (i == 0 && j == this.bloquesPorLinea - 1)
                     {
                         this.bloqueVacio = bloque;
                     }
                     
                 }
             }
             Camera.main.orthographicSize = (float)this.bloquesPorLinea * 0.55f;
             this.inputs = new Queue<Bloque>();
         }

This is the function that checks if the puzzle is assembled (original positions)

private void comprobarSiGano()
         {
             Bloque[,] array = this.bloques;
             int length = array.GetLength(0);
             int length2 = array.GetLength(1);
             for (int i = 0; i < length; i++)
             {
                 for (int j = 0; j < length2; j++)
                 {
                     Bloque bloque = array[i, j];
                     if (!bloque.estaDondeEmpezo())
                     {
                         return;
                     }
                 }
             }
             // ACA ES CUANDO GANO
             this.state = Puzzle.EstadoDelPuzzle.Gano;
             cantidadPuntos += 1000;
             contadorTiempo = contadorTiempo;
             estaJugando = false;
             this.bloqueVacio.gameObject.SetActive(true);
             
             
     
         }

The function on the line that creates the puzzle (this one):

 bloque.Init(new Vector2Int(j, i), array[j, i]); 

Is this one:

     public void Init(Vector2Int coordenadaEmpieza, Texture2D imagen)
        {
            this.coordenadaEmpieza = coordenadaEmpieza;
            this.coordenada = coordenadaEmpieza;
            base.GetComponent<MeshRenderer>().material = Resources.Load<Material>("Block");
            base.GetComponent<MeshRenderer>().material.mainTexture = imagen;
        }

I really don’t know how to save it. When the game starts, you have to press on the screen then the puzzle starts shuffling random.