Unity如何保存玩家的数据(Unity的二进制序列化)

文章目录

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

什么是二进制序列化

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 updatevoid 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.mzph.cn/bicheng/34325.shtml

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

相关文章

太全了吧?CISP全类别详细介绍,看完不迷惑

今天聊聊CISP,注册信息安全专业人员证。 很多人以为说CISP就是个证书,没这么简单,这里面区别可大了。 CISP根据工作领域和实际岗位需要,分为综合型、攻防领域、IT审计、软件开发、数据治理、电子取证和云安全领域等17项证书。 这么…

C++系统相关操作6 - 获取二进制程序的位数(32位或64位)

1. 关键词2. sysutil.h3. sysutil.cpp4. 测试代码5. 运行结果6. 源码地址 1. 关键词 关键词&#xff1a; C 程序 32位 64位 跨平台 实现原理&#xff1a; 根据指针地址的位数来判断程序是32位还是64位。 2. sysutil.h #pragma once#include <cstdint> #include &l…

在容器中共享本地文件

在容器中共享本地文件 目录 卷与绑定挂载的对比在主机和容器之间共享文件Docker 访问主机文件的文件权限试一试 运行一个容器使用绑定挂载在 Docker Dashboard 中访问文件停止容器 额外资源下一步 每个容器都有一切需要运行的资源&#xff0c;而不依赖于主机机器上预先安装的…

怎么样才能踏入机器视觉这个行业?

机器视觉从业的定位层次&#xff1a; 00001. 底层算法开发 00002. 应用软件开发 00003. 视觉系统集成 00004. 视觉系统使用刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「机器视觉的资料从专业入门到高级教程」&#xff0c; 00005. 点个关注在评论区回…

[FreeRTOS 功能应用] 信号量 功能应用

文章目录 一、基础知识点二、代码讲解三、结果演示四、代码下载 一、基础知识点 [FreeRTOS 基础知识] 信号量 概念 [FreeRTOS 内部实现] 信号量 [FreeRTOS 内部实现] 创建任务 xTaskCreate函数解析 本实验是基于STM32F103开发移植FreeRTOS实时操作系统&#xff0c;信号量实战…

python-pytorc+bert句子分类0.1.000

这里写目录标题 引入包加载预训练模型加载数据文件定义数据实例化数据集使用loader加载数据设定最大句子长度定义加padding的函数定义加collate_fn函数使用DataLoader加载数据 定义模型测试预训练模型输出测试预训练模型输出定义自己的模型 参考 引入包 import torch from tor…

this.$prompt 提示框增加文本域并修改文本域高度

2024.06.24今天我学习了如何对提示框增加文本域的方法&#xff0c;效果如下&#xff1a; 代码如下&#xff1a; <script>methods:{reject_event(){this.$prompt(驳回内容, 提示, {confirmButtonText: 确定,cancelButtonText: 取消,inputType: textarea,inputPlaceholder…

计算机网络(数据链路层)

数据链路层概述 数据链路层位于计算机网络的低层&#xff0c;且在物理层之上&#xff0c;数据链路层使用的信道主要有以下两种类型。 &#xff08;1&#xff09;点对点通信。在信道上使用一对一的点对点通信。 &#xff08;2&#xff09;广播信道。这种信道使用一对多的广播通…

【linux】详解——库

目录 概述 库 库函数 静态库 动态库 制作动静态库 使用动静态库 如何让系统默认找到第三方库 lib和lib64的区别 /和/usr/和/usr/local下lib和lib64的区别 环境变量 配置相关文件 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 简介&#xff1a;C站最萌博主 相关…

DDK电通拧紧MFC-S060控制器过流维修

一、DDK伺服拧紧轴控制器过流故障的成因 1. 电源电压过低&#xff1a;当电源电压过低时&#xff0c;控制器可能会出现过流现象。 2. 负载过大&#xff1a;当负载过大时&#xff0c;DDK电通拧紧机控制器MFC-S060的电流也会随之增大&#xff0c;可能导致过流故障。 3. 控制器内部…

自动调整QTableView列宽以适应窗口大小

问题描述 十年前&#xff0c;有人提出了一个问题&#xff1a;当我使用自定义模型来展示 QTableView&#xff0c;并固定了三列时&#xff0c;初始窗口显示正常&#xff0c;但当我调整窗口大小时&#xff0c;QTableView 会随之调整大小&#xff0c;而列宽却保持不变。我想让列宽…

远程连接mysql数据库的详细配置

1. 确认 MySQL 服务器配置 首先&#xff0c;确认 MySQL 服务器的配置允许远程连接。您需要编辑 MySQL 的配置文件&#xff0c;并确保以下设置正确&#xff1a; bind-address&#xff1a;这个参数控制 MySQL 监听的 IP 地址。如果要允许任何 IP 地址连接&#xff0c;请将其设置…

手写 Promise 的实现

手写 Promise 的实现 从实现原理的角度分析 Promise 是什么 从语法上说&#xff0c;Promise 是一个对象&#xff0c;从它可以获取异步操作的消息。ES6 原生提供了Promise对象。 Promise内部有三种状态&#xff1a;pending&#xff08;进行中&#xff09;、fulfilled&#xf…

开箱即用:一个易用的开源表单工具!【送源码】

随着互联网的普及&#xff0c;表单应用场景越来越广泛&#xff0c;从网站注册、调查问卷到考试测评&#xff0c;无处不在。传统的表单制作方式需要一定的代码基础&#xff0c;对于不懂编程的小伙伴来说&#xff0c;无疑是一道门槛。 今天&#xff0c;给大家分享一款开源的表单…

如何理解redis是单线程的

写在文章开头 在面试时我们经常会问到这样一道题 你刚刚说redis是单线程的&#xff0c;那你能不能告诉我它是如何基于单个线程完成指令接收与连接接入的&#xff1f;这时候我们经常会得到沉默&#xff0c;所以对于这道题&#xff0c;笔者会直接通过3.0.0源码分析的角度来剖析…

[数据集][目标检测]花生米计数霉变检测数据集VOC+YOLO格式387张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;387 标注数量(xml文件个数)&#xff1a;387 标注数量(txt文件个数)&#xff1a;387 标注类别…

使用Leaflet和瓦片地图实现离线地图的技术指南

引言 在现代的Web应用中&#xff0c;地图服务扮演着越来越重要的角色。然而&#xff0c;在一些特殊环境下&#xff0c;如偏远地区或网络环境不稳定的情况下&#xff0c;依赖在线地图服务可能会受到限制。因此&#xff0c;实现离线地图功能成为了一个重要的需求。本文将介绍如何…

【数据库】Oracle 分区表与 TRUNC 函数的优化应用

在 Oracle 数据库中&#xff0c;分区表是一种强大的数据管理工具&#xff0c;它允许将大型表分割成更小、更易于管理的部分&#xff0c;称为分区。每个分区可以独立地进行管理&#xff0c;包括备份、恢复和优化。分区表特别适用于处理大量数据&#xff0c;可以显著提高查询性能…

Redis入门与应用(1)

Redis的技术全景 Redis是一个开源的基于键值对&#xff08;Key-Value&#xff09;的NoSQL数据库&#xff0c;使用ANSI C语言编写&#xff0c;支持网络&#xff0c;基于内存但支持持久化。它性能优越&#xff0c;并提供多种语言的API。我们可以将Redis视为一个巨大的Map&#x…

《Java面试题集中营》- Java并发

《Java并发编程的艺术》、《Java并发编程之美》 运行中的线程能否强制杀死 Jdk提供了stop()方法用于强制停止线程&#xff0c;但官方并不建议使用&#xff0c;因为强制停止线程会导致线程使用的资源&#xff0c;比如文件描述符、网络连接处于不正常的状态。建议使用标志位的方…