Как сохранить состояние игры?

27

Какую процедуру выполняют игровые программисты для сохранения и возобновления игрового состояния? как файлы / сопоставления. Я хочу сохранить его для игры Tower Defense и использую игровой движок Unity3D.

Сайед
источник

Ответы:

16

Я обычно не думаю о снимке памяти, а просто делаю список значений, которые необходимо сохранить между сеансами, и сохраняю эти значения во внешнем файле.

Это, конечно, зависит от потребностей вашей конкретной игры, но обычно я просто сохраняю состояние текущего уровня (т.е. где все враги, каково их здоровье и т. Д.), А затем вещи более высокого уровня, такие как уровни игрока уже завершено.

jhocking
источник
3
+1 Вот как я это делаю. Я пишу то, что мне нужно, в двоичный файл. И, если мне нужно добавить что-то новое, я добавляю это в конец, чтобы не ломать старые файлы сохранения.
ХаосТехник
Это хороший совет, чтобы не ломать старые файлы сохранения, хотя добавление данных в конец не имеет отношения к тому, как я сохраняю данные. Я делаю это путем сериализации / десериализации словаря, и порядок в этой структуре данных не имеет значения.
Джоккинг
(в основном, код в ответе
Джонаса
10

Этот ответ специфичен для Unity3d .
В Unity большинство классов сериализуемы, это означает, что вы можете транслировать полные объекты Unity на диск. Следующий UnityScript-Code - это способ сериализации объекта, сохранения его на диск и загрузки его снова (после загрузки вы должны отлить объект):

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;
                }       
        }
}
Джонас
источник
2
Помимо использования C #, вы также хотели бы использовать PlayerPrefs. Они кроссплатформенные, вы не можете сделать IO на Web / iOS / Android. unity3d.com/support/documentation/ScriptReference/… (хороший пример!)
TJHeuvel
PlayerPrefs менее гибки, они действительно кроссплатформенные и идеально подходят для хранения отдельных или несвязанных значений. Но на Windows PlayerPrefs хранятся в реестре в виде открытого текста.
Джонас
7
Если вы уже сериализуете, почему бы не сериализовать его в строку и сохранить в PlayerPrefs. Конечно, она менее гибкая, но это практически единственное решение для кроссплатформенной игры.
TJHeuvel
2
PlayerPrefs отлично подходит для хранения небольших данных, таких как настройки, но для целых сохраненных
игр
2
@TJHeuvel: «Вы не можете делать IO на Web / iOS / Android» Вы, безусловно, можете сделать IO на мобильном телефоне
Przemysław Wrzesiński
2

Для ТД я бы, наверное, сэкономил исключительно между волнами. Таким образом, все, о чем вы должны думать - это башни. Поместите несколько автоматических точек сохранения в уровни, не более 10 минут между ними, но, вероятно, предпочтительнее меньше.

Конечно, если ваши уровни достаточно короткие, вы можете просто сохранить только статус кампании.

AAAAAAAAAAAA
источник
1

Когда я ссылаюсь на текущее состояние игры, я имею в виду моментальный снимок памяти в момент сохранения. Вы должны иметь возможность воссоздать это из данных, которые вы собираетесь хранить на жестком диске.

Проще всего сериализовать все классы, у которых есть данные, которые должны быть постоянными, и выгрузить их на жесткий диск, выполнив дамп памяти. Проблема в том, что изменение ваших классов изменит количество / типы сериализованных значений и нарушит старые сохранения. Кроме того, потому что вы сохраняете все, это увеличивает время загрузки. Более эффективно отмечать отдельные поля, которые фактически необходимы для перестройки текущего «снимка памяти» с любой системой атрибутов, которую использует ваш сериализатор / IDE. Затем восстановите «снимок памяти» из этих сохраненных данных.

Кроме того, я никогда не использовал Unity, поэтому в него может быть встроено что-то. Однако это типичный подход.

ClassicThunder
источник
ты имеешь в виду, что я должен хранить свои состояния в файле?
Сайед
1
@ Да, в конце дня его нужно записать в какой-нибудь файл, так как состояние приложения не будет сохраняться в памяти. В частности, в Unity вы можете использовать класс PlayerPrefs (который, я думаю, на самом деле хранит вещи в реестре в Windows), если вы хотите избежать всего, что нужно для чтения / записи файлов.
Тетрад