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


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.