¿Cómo se guarda el estado del juego?

27

¿Cuál es el procedimiento seguido por los programadores de juegos para guardar y reanudar el estado del juego? como archivos / mapeos. Quiero guardarlo para el juego Tower Defense y estoy usando el motor de juego Unity3D.

Syed
fuente

Respuestas:

16

Generalmente no pienso en términos de una instantánea de memoria, sino que simplemente hago una lista de los valores que deben guardarse entre sesiones y los guardo en un archivo externo.

Esto depende, por supuesto, de las necesidades de tu juego específico, pero generalmente simplemente guardo el estado del nivel actual (es decir, dónde están todos los enemigos, cuál es su salud, etc.) y luego cosas de nivel superior como los niveles del jugador Ya se ha completado.

jhocking
fuente
3
+1 Así es como lo hago. Escribo lo que necesito en un archivo binario. Y, si necesito agregar algo nuevo, lo agrego al final para que no rompa los archivos guardados viejos.
chaosTechnician
Es un buen consejo para no romper los archivos guardados antiguos, aunque agregar datos al final es irrelevante para la forma en que guardo los datos. Lo hago serializando / deserializando un diccionario, y el orden es irrelevante en esa estructura de datos.
jhocking
(básicamente, el código en la respuesta de jonas, con mi objeto siendo un diccionario)
jhocking
10

Esta respuesta es específica de Unity3d .
En Unity, la mayoría de las clases son serializables, esto significa que puede transmitir objetos completos de Unity al disco. El siguiente código UnityScript es una forma de serializar un objeto, guardarlo en el disco y cargarlo nuevamente (después de cargarlo, debe lanzar el objeto):

import System;
import System.IO;
import System.IO.Stream;
import System.Runtime.Serialization;
import System.Runtime.Serialization.Formatters.Binary;

class SaveLoad {
        public static function SaveFile(filename:String, obj:Object):void {
                try {
                        Debug.Log("Writing Stream to Disk.", SaveLoad);
                        var fileStream:Stream = File.Open(filename, FileMode.Create);
                        var formatter:BinaryFormatter = new BinaryFormatter();
                        formatter.Serialize(fileStream, obj);
                        fileStream.Close();
                } catch(e:Exception) {
                        Debug.LogWarning("Save.SaveFile(): Failed to serialize object to a file " + filename + " (Reason: " + e.ToString() + ")");
                }
        }

        public static function LoadFile(filename:String):Object {
                try {
                        Debug.Log("Reading Stream from Disk.", SaveLoad);
                        var fileStream:Stream = File.Open(filename, FileMode.Open, FileAccess.Read);
                        var formatter:BinaryFormatter = new BinaryFormatter();
                        var obj:Object= formatter.Deserialize(fileStream);
                        fileStream.Close();
                        return obj;
                } catch(e:Exception) {
                        Debug.LogWarning("SaveLoad.LoadFile(): Failed to deserialize a file " + filename + " (Reason: " + e.ToString() + ")");
                        return null;
                }       
        }
}
jonas
fuente
2
Además de usar C #, también querrás usar PlayerPrefs. Son multiplataforma, no puedes hacer IO en Web / iOS / Android. unity3d.com/support/documentation/ScriptReference/… (¡Buena muestra!)
TJHeuvel
Los PlayerPrefs son mucho menos flexibles, son multiplataforma y son perfectos para almacenar valores únicos o no relacionados. Pero en Windows PlayerPrefs se almacenan en el registro, texto sin formato.
jonas
77
Si ya está serializando, ¿por qué no serializarlo en una cadena y almacenarlo en PlayerPrefs? Claro que es menos flexible, pero es prácticamente la única solución para un juego multiplataforma.
TJHeuvel
2
PlayerPrefs es ideal para almacenar datos pequeños, como configuraciones, pero para juegos
jhocking
2
@TJHeuvel: "no puedes hacer IO en Web / iOS / Android" Definitivamente puedes hacer IO en dispositivos móviles
Przemysław Wrzesiński
2

Para un TD probablemente ahorraría exclusivamente entre olas. De esa manera, todo lo que tiene que pensar son las torres. Ponga algunos puntos de guardado automático en los niveles, no más de 10 minutos entre ellos, pero probablemente sea preferible menos.

Por supuesto, si sus niveles son lo suficientemente cortos, simplemente podría guardar nada más que el estado de la campaña.

aaaaaaaaaaaa
fuente
1

Cuando me refiero al estado actual del juego, me refiero a la instantánea de la memoria en el momento de guardar. Debe poder recrear eso a partir de los datos que va a almacenar en su HDD.

Es más fácil simplemente serializar todas las clases que tienen datos que deben ser persistentes y volcarlos en el HDD, esencialmente realizando un volcado de memoria. El problema con esto es que alterar sus clases cambiará el número / tipos de valores serializados y romperá los antiguos guardados. También porque está guardando todo, aumenta los tiempos de carga. Es más eficiente marcar campos individuales que son realmente necesarios para reconstruir la "instantánea de memoria" actual con cualquier sistema de atributos que utilice su serializador / IDE. Luego reconstruya la "instantánea de memoria" a partir de los datos guardados.

Además, nunca he usado Unity antes, por lo que puede tener algo incorporado. Sin embargo, este es el enfoque típico.

Trueno clásico
fuente
¿Quieres decir que tengo que almacenar mis estados en un archivo?
Syed
1
@Sí, sí, al final del día tiene que escribirse en un archivo de algún tipo ya que el estado de la aplicación no se guardará en la memoria. Con Unity específicamente, puede usar la clase PlayerPrefs (que creo que realmente almacena cosas en el registro en Windows) si desea evitar todo el material de lectura / escritura de archivos.
Tetrad