Unity保存玩家的数据到文件中(Unity的二进制序列化)

news2024/11/26 18:34:27

文章目录

  • 文章运行环境
  • 什么是二进制序列化
  • 读写文件
    • 构造函数
  • 自定义二进制序列化

文章运行环境

Unity2022

什么是二进制序列化

Unity中的二进制序列化是一种将游戏对象或数据结构转换为二进制格式的过程,以便于存储或网络传输。这使数据能够以高效的方式保存,同时在需要时可以被正确地恢复(反序列化)回原始状态。二进制序列化对于保存游戏进度、网络同步数据或资源打包(如AssetBundles)特别有用。

二进制序列化通常比文本格式(如JSON、XML)更快,占用空间更小,但可能不如文本格式易于调试或跨平台兼容。

读写文件

在C#中,我们用FileStream类来读取、写入文件。它允许程序以流的形式访问文件系统中的文件,支持读取、写入、追加等多种操作模式。

FileStream类是.NET框架中一个非常核心的类,它位于System.IO命名空间下。

我们先来看一行代码,感受一下FileStream类读写文件的操作:

using FileStream stream = new FileStream(filePath, FileMode.Create);

这段代码创建了一个新的FileStream对象,用于与文件系统交互。这里有几个关键点:

new FileStream(filePath, FileMode.Create) 这里调用了FileStream的构造函数,它接受两个主要参数:

  • filePath: 字符串类型,表示要打开或创建的文件路径。如果路径不包含驱动器字母,它会被视为相对于当前工作目录的路径。
  • FileMode.Create: FileMode枚举的一个成员,指定了打开或创建文件的模式。在这个例子中我们用的是Create模式,表示如果指定的文件已经存在,则会覆盖现有文件(即删除原文件内容并开始写入新数据)。如果文件不存在,则会创建一个新文件。

另外示例使用了using语句,using关键字在这里用于确保FileStream对象在不再需要时(比如方法执行完毕或作用域结束)能够被正确且及时地关闭和释放相关资源。这有助于防止文件句柄泄露,保证系统资源的有效管理。使用using块可以自动调用Dispose()方法,即使在发生异常的情况下也能确保资源的释放。

构造函数

FileStream类提供了多个构造函数,以适应不同的使用场景。最基本的构造函数如下:

public FileStream(string path, FileMode mode);

其中,path是文件的路径,前面已经说的很详细了,这里不多赘述,mode决定了如何打开或创建文件,它是一个FileMode枚举值。除了FileMode.Create(如之前提到的,用于创建新文件或覆盖现有文件),还有其他几种模式,包括:

  • FileMode.Open:打开现有文件,如果文件不存在则抛出异常。
  • FileMode.OpenOrCreate:如果文件存在则打开,否则创建新文件。
  • FileMode.Append:打开文件以追加内容,如果文件不存在则创建新文件。
    当然还有其他模式,这里不多说了,大家可以查阅文档。

除了上述基本构造函数外,还有其他构造函数,例如可以通过额外的参数指定文件访问权限(如FileAccess.ReadWrite)、文件共享选项(FileShare.None, FileShare.Read, 等)以及文件选项(如FileOptions.Asynchronous)。这里暂不展开。

自定义二进制序列化

我们可以使用BinaryFormatter来实现更复杂的自定义序列化需求,虽然不是Unity引擎直接推荐的方法。

这个类是.NET的,完全限定名是System.Runtime.Serialization.Formatters.Binary.BinaryFormatter,我们用这个类来进行二进制序列化。这种方法允许你精细控制哪些数据被序列化,并且可以将数据写入到文件或内存流中。

接下来我们写一个例子来学习。首先,定义一个简单的PlayerData类,该类标记有[Serializable]属性,这样BinaryFormatter就能识别并处理它:

[Serializable]
public class PlayerData
{
    public string playerName;
    public int score;
    public DateTime lastPlayed;

    public PlayerData(string name, int score, DateTime time)
    {
        this.playerName = name;
        this.score = score;
        this.lastPlayed = time;
    }
}

接下来,使用BinaryFormatter进行序列化和反序列化:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
public class DataSaver : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 创建一个示例对象
        PlayerData data = new("玩家1", 1000, DateTime.Now);

        // 序列化对象到文件
        SaveToFile(data, "game.save");

        // 从文件反序列化对象
        PlayerData loadedData = LoadFromFile("game.save");

        // 打印加载的数据,验证是否保存成功
        Debug.Log($"玩家名: {loadedData.playerName}");
        Debug.Log($"分数: {loadedData.score}");
        Debug.Log($"上次游玩时间: {loadedData.lastPlayed}");
    }
    static void SaveToFile(PlayerData data, string filePath)
    {
        using FileStream stream = new(filePath, FileMode.Create);
        BinaryFormatter formatter = new();
        formatter.Serialize(stream, data);
    }

    static PlayerData LoadFromFile(string filePath)
    {
        if (File.Exists(filePath))
        {
            using FileStream stream = new(filePath, FileMode.Open);
            BinaryFormatter formatter = new();
            return (PlayerData)formatter.Deserialize(stream);
        }
        else
        {
            throw new FileNotFoundException($"文件没找到: {filePath}");
        }
    }
}

在场景内创建一个物体,命名为DataSaver,然后将脚本挂载在该物体上。
在这里插入图片描述
运行程序,观察控制台
在这里插入图片描述

需要注意的是,当序列化数据结构发生变化时,需要考虑向前和向后兼容问题,确保旧数据能被正确反序列化,或提供数据迁移策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1875131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络==>总论v4

既然是写ICT方面的文章,就要不断更新版本,不是文学,可以一劳永逸,如果不更新,看十年前或者二十年前的书意义不大,这就是为啥看到很多编程书都更新到第十几版了,因为要与时俱进。 在去一个地方旅…

JS(JavaScript)事件处理(事件绑定)

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

C语言单链表的算法之删除节点

一:为什么要删除节点 (1)有时候链表中节点的数据不想要了,就要删除这个节点 二:删除节点的两个步骤 (1)第一步:找到这个节点 (2)第二步:删除这个…

麒麟桌面系统CVE-2024-1086漏洞修复

原文链接:麒麟桌面操作系统上CVE-2024-1086漏洞修复 Hello,大家好啊!今天给大家带来一篇在麒麟桌面操作系统上修复CVE-2024-1086漏洞的文章。漏洞CVE-2024-1086是一个新的安全漏洞,如果不及时修复,可能会对系统造成安全…

Rust单元测试、集成测试

单元测试、集成测试 在了解了如何在 Rust 中写测试用例后,本章节我们将学习如何实现单元测试、集成测试,其实它们用到的技术还是上一章节中的测试技术,只不过对如何组织测试代码提出了新的要求。 单元测试 单元测试目标是测试某一个代码单…

算法金 | K-均值、层次、DBSCAN聚类方法解析

大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 聚类分析概述 聚类分析的定义与意义 聚类分析(Clustering Analysis)是一种将数据对象分成多个簇(…

AI 音乐生成器 MusicGPT,同声传译StreamSpeech!Web短视频平台Sharine

AI 音乐生成器 MusicGPT,同声传译StreamSpeech!Web短视频平台Sharine。 项目简介 MusicGPT 是一款应用程序,允许在任何平台上以高性能方式本地运行最新的音乐生成 AI 模型,而无需安装 Python 或机器学习框架等严重依赖项。 目前它仅支持 Me…

【python】OpenCV—Aruco

文章目录 Detect ArucoGuess Aruco Type Detect Aruco 学习参考来自:OpenCV基础(19)使用 OpenCV 和 Python 检测 ArUco 标记 更多使用细节可以参考:【python】OpenCV—Color Correction 源码: 链接:http…

二进制方式部署consul单机版

1.consul的下载 mkdir -p /root/consul/data && cd /root/consul wget https://releases.hashicorp.com/consul/1.18.0/consul_1.18.0_linux_amd64.zip unzip consul_1.18.0_linux_amd64.zip mv consul /usr/local/bin/ 2.配置文件 // 配置文件路径: /roo…

Vue 项目运行时,报错Error: Cannot find module ‘node:path‘

Vue 项目运行时,报错Error: Cannot find module ‘node:path’ internal/modules/cjs/loader.js:883throw err;^Error: Cannot find module node:path Require stack: - D:\nodejs\node_modules\npm\node_modules\node_modules\npm\lib\cli.js - D:\nodejs\node_mo…

240628_昇思学习打卡-Day10-SSD目标检测

240628_昇思学习打卡-Day10-SSD目标检测 今天我们来看SSD(Single Shot MultiBox Detector)算法,SSD是发布于2016年的一种目标检测算法,使用的是one-stage目标检测网络,意思就是说它只需要一步,就能把目标检…

国内多个库被 rsc 钉上 Go 耻辱柱。。。

大家好,我是煎鱼。 这还是比较突然的,下午正努力打工。国内社区群里突然就闹腾起来了。 仔细一看,原来是 Go 核心团队负责人 rsc,又冷不丁搞大招 😅。他直接把国内好几个知名库给直接钉上了 Go 源码库的耻辱柱上了。 如…

普元EOS学习笔记-EOS8.3精简版安装

前言 普元EOS是优秀的高低开结合的企业应用软件开发框架。 普元:这是普元公司的名字,普元信息,上市公司哦,这里就不过多安利了。 EOS:普元公司的企业应用开发系统,开发语言是基于Java,技术框…

JavaScript(2)——输入输出和执行顺序

目录 JS的输入输出语法 输出: 输入 JS的代码执行顺序 字面量 JS的输入输出语法 输出: document.write(内容)alert(内容) 页面弹出警告框console.log(内容) 控制台输出语法,程序员调试使用 作用:向body输出内容 注意&…

zabbix-server的搭建

zabbix-server的搭建 部署 zabbix 服务端(192.168.99.180) rpm -ivh https://mirrors.aliyun.com/zabbix/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm cd /etc/yum.repos.d sed -i s#http://repo.zabbix.com#https://mirrors.aliyun.com/zabbix# zabbix.r…

音频分离人声和伴奏可以实现吗?手机人声分离工具10款无偿分享!

随着科技的飞速发展,音频处理技术已经取得了显著的进步,其中音频分离人声和伴奏已成为现实。这一技术不仅为音乐制作人和音频工程师提供了便利,更为广大音乐爱好者提供了无限的创作可能性。本文将为大家分享10款手机人声分离工具,…

前端面试题(基础篇十二)

一、link标签定义、与import的区别 link 标签定义文档与外部资源的关系。 link 元素是空元素,它仅包含属性。 此元素只能存在于 head 部分,不过它可出现任意数。 link 标签中的 rel 属性定义了当前文档与被链接文档之间的关系。常见的 stylesheet 指的是…

C# 警告 warning MSB3884: 无法找到规则集文件“MinimumRecommendedRules.ruleset”

警告 warning MSB3884: 无法找到规则集文件“MinimumRecommendedRules.ruleset” C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\amd64\Microsoft.CSharp.CurrentVersion.targets(129,9): warning MSB3884: 无法找到规则集文件“MinimumRe…

好书速览-深入理解JVM-Part1

文章目录 第二章、Java内存区域与内存溢出异常2.1 概述2.2 运行时数据区域程序计数器(program Counter Register)Java虚拟机栈本地方法栈堆方法区运行时常量池直接内存 2.3 对象生命周期2.3.1 对象的创建2.3.2 对象的内存布局对象头类型指针对齐填充 2.3.3 对象的访…

WordPress免费模板:惊艳动态效果,打造视觉盛宴

WordPress免费模板:惊艳动态效果,打造视觉盛宴 我们为您带来了一款独具特色的WordPress免费模板,这款模板以其独特的动态效果设计,特别是引人注目的动态banner图片效果,为您的网站注入活力,打造一场视觉盛…