Як ви зберігаєте ігровий стан?


27

Яку процедуру виконують ігрові програмісти для збереження та відновлення ігрового стану? як файли / відображення. Я хочу зберегти його для гри в оборону башти, і я використовую ігровий движок юни3D.

Відповіді:


16

Я, як правило, не думаю про зйомку пам'яті, але я просто складаю список, які значення потрібно зберігати між сеансами і зберігати ці значення у зовнішній файл.

Це, звичайно, залежить від потреб вашої конкретної гри, але зазвичай я просто зберігаю стан поточного рівня (тобто, де всі вороги, яке їхнє здоров'я тощо), а потім речі вищого рівня, наприклад, який рівень гравця вже завершено.


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. unit3d.com/support/documentation/ScriptReference/… (Хоча приємний зразок!)
TJHeuvel

PlayerPrefs набагато менш гнучкі, вони дійсно є кросплатформою, і вони ідеально підходять для зберігання одиничних або неспоріднених значень. Але в Windows PlayerPrefs зберігаються в реєстрі, простому тексті.
Джонас

7
Якщо ви вже серіалізуєте, чому б не серіалізувати його до String і зберегти його в PlayerPrefs. Звичайно, вона менш гнучка, але це майже єдине рішення для кросплатформної гри.
TJHeuvel

2
PlayerPrefs чудово підходить для зберігання невеликих даних, таких як налаштування, але для цілих ігор збереження слід використовувати Application.persistentDataPath docs.unity3d.com/ScriptReference/…
jhocking

2
@TJHeuvel: "Ви не можете робити IO в Інтернеті / iOS / Android" Ви, безумовно, можете робити IO на мобільних пристроях
Przemysław Wrzesiński

2

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

Звичайно, якщо ваші рівні досить короткі, ви можете просто зберегти нічого, крім статусу кампанії.


1

Коли я маю на увазі поточний стан гри, я маю на увазі знімок пам'яті в момент збереження. Вам потрібно вміти відтворити це з даних, які ви збираєтеся зберігати на вашому жорсткому диску.

Найпростіше просто серіалізувати всі ваші класи, у яких є дані, які повинні бути стійкими, і скинути їх на жорсткий диск, по суті виконуючи дамп пам'яті. Проблема з цим полягає в тому, що зміна класів змінить кількість / типи серіалізованих значень і порушить старі збереження. Також тому, що ви економите все, це збільшує час завантаження. Його ефективніше позначити окремі поля, які фактично потрібні для відновлення поточного "знімка пам'яті" за допомогою будь-якої системи атрибутів, яку використовує ваш серіалізатор / IDE. Потім відновіть "знімок пам'яті" з цих збережених даних.

Також я ніколи раніше не використовував Unity, щоб у ньому було щось вбудоване. Однак це типовий підхід.


ти маєш на увазі, що я повинен зберігати свої штати у файлі?
Проведено

1
@ Так, наприкінці дня його потрібно записати у якийсь файл, оскільки стан програми не буде збережено в пам'яті. У Unity спеціально ви можете використовувати клас PlayerPrefs (який, на мою думку, насправді зберігає речі в реєстрі в Windows), якщо ви хочете уникнути того, щоб цілий файл читав / писав.
Тетрад
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.