纯原创,自制

本人还是个在校的高中生,能力不精如果有漏洞欢迎指出

先放出我们示范项目的样子

演示项目工程文件下载

后面会在B站发详细的视频教程(所以文章之后肯会改)

嫌麻烦的直接复制到项目里就可以用哦

(全部的SaveSystem源码最后放出方便大家复制)

可以存储含有常见值类型和字符串类型字段的对象

使用方法就是SaveSystem.Save<存储的对象类型>(存储数据的对象名);

加载就是SaveSystem.Load<读取的对象类型>(读取数据的对象名);

就是这么简单,只要你的类里的字段是常见值类型和字符串类型就可以

不常见的值类型可看我文章中Load函数的注释,在switch语句中添加即可

使用这个就可以存了

(注:使用时需要using system,UnityEngine,System.Reflection,System.IO这几个命名空间)

(其他地方也可以使用这个存档方法,把代码中的所有Debug语句删除就可以不使用UnityEngine)

(只有加了[CanSave]特性的类才可以被存档系统接受,防止不兼容的类被保存造成的错误)

(就是为了让大家检查一下才加了这个特性)

(更详尽的使用方法在教程中哦)

使用UI来显示我们数据的变化,然后save和Load按钮实现读档和存档的功能

新建SaveSystem脚本,删除掉编辑器自动生成的Update函数和Start函数,让我们写下第一个Sava函数,我会写好注释讲解每个初学者可能不知道的对象(够贴心吧)

public class SaveSysteam
{//泛型以保存各种类型的数据public static void Save<T>(T obj){int N=0;//创建一个int变量来控制我要保存的数据所在数组位置string[]Data=new string[10];Type type = typeof(T);//利用反射获得类的信息if (type.IsDefined(typeof(CanSaveAttribute), false)){//这个if先不看可以,就是判断这个类是否存在我们后面的自定义特性,不存在是不可以存的哦//因为存的数据要求是值类型或字符串类型,为了防止其他人使用不会注意,我们要写一个特性,起提示作用CanSaveAttribute can=type.GetCustomAttribute<CanSaveAttribute>();//获得该类下的特性FieldInfo[] fields = type.GetFields();//利用反射获得该类的所有字段Data[N] = can.author;//保存特性中的信息N++;Data[N] = can.versionNumber;N++;//从上个注释到这都是存特性的foreach (FieldInfo field in fields){//遍历字段的数组获得每个字段的值,并转换成字符串类型Data[N] = Convert.ToString(field.GetValue(obj));N++;// Debug.Log(field.GetValue(obj));}File.WriteAllLines(@"D:\\c#\\存档系统\\GameData.txt", Data);//前面的参数是存的路径,请您自己改哦,后面的参数是存完数据的string数组Debug.Log("IsSave");//控制台输出保存的消息}else//如果不包含特性的警告{Debug.LogError("你保存了一个不包含特性CanSaveAttribute的类,请检查保存的类是否符合规定");}}}

这就是我们的Save函数了,是不是比较简单呢,那么接下来让我们在SaveSystem类里加入Load函数

//泛型老样子(不会有人没注意听讲吧)public static void Load<T>(T obj){int N = 0;//N的作用和上面的一样Type type = typeof(T);if (type.IsDefined(typeof(CanSaveAttribute), false)){CanSaveAttribute can = type.GetCustomAttribute<CanSaveAttribute>();FieldInfo[] fields = type.GetFields();string[] Data = new string[10];Data = File.ReadAllLines(@"D:\\c#\\存档系统\\GameData.txt");//按行读取文件里的数据//上面用到的保存方法也是按行读取if (Data[N] == can.author && Data[N+1]==can.versionNumber){//判断要读取的类的特性里的信息和当时存储的信息是否一致N = N + 2;foreach (FieldInfo field in fields){//遍历要读取的类的字段的类型,好把数据按类型传回去,因为存的都是string类型的switch (Convert.ToString(field.FieldType)){//用switch语句,现在字段的类型是啥就把string转换成什么//为什么变量类型都是这些名字呢//因为反射获得的字段的类型都是对应的.NET Framework 中的类型// 下张图片我会放一个表,C#类型对应的.NET Framework 类型case "System.Int32":field.SetValue(obj, Convert.ToInt32(Data[N]));//设置字段值的方法SetValue,前面要求的参数是你要设置字段的对象,可以这么理解//但是我建议你自己查一下微软的文档里面有详细解释break;case "System.Double":field.SetValue(obj, Convert.ToDouble(Data[N]));break;case "System.String":field.SetValue(obj, Data[N]);break;case "System.Single":field.SetValue(obj, Convert.ToSingle(Data[N]));break;case "System.Decimal":field.SetValue(obj, Convert.ToDecimal(Data[N]));break;}N++;}}else{Debug.LogError("现在的类与存储时的特性有所差异,可以查看文件中的原作者名字取得联系并修改");}}else{Debug.LogError("你加载了一个不包含特性CanSaveAttribute的类,请检查加载的类是否符合规定或存在");}}

下面是我答应的表(是在别的博客里翻到的,但是实在找不到原作者了,无法发链接,感谢作者整理)

(如果错误就去微软文档查最新的)

C# 类型       .NET Framework 类型bool            System.Boolean               4Byte 32bit ,true或者false,默认值为falsebyte            System.Byte                1Byte 8bit 无符号整数 无符号的字节,所存储的值的范围是0~255,默认值为0sbyte         System.SByte 1Byte8bit 有符号整数 带符号的字节,所存储的值的范围是-128~127,默认值为0char           System.Char 2Byte 16bit 无符号Unicode字符,默认值为’\0’decimal      System.Decimal16Byte 128bit十进制数不遵守四舍五入规则的十进制数,28个有效数字,通常用于财务方面的计算,默认值为0.0mdouble       System.Double8Byte 64bit双精度的浮点类型,默认值为0.0dfloat          System.Single4Byte 32bit单精度的浮点类型,默认值为0.0fint             System.Int324Byte 32bit有符号整数,默认值为0uint           System.UInt324Byte 32bit无符号整数,默认值为0long          System.Int648Byte 64bit有符号整数,默认值为0

然后我们要写之前挖的坑了,没错就是特性

//哈哈哈,自定义特性上还要加特性,这个特性标明它是给类用的
[AttributeUsage(AttributeTargets.Class)]
//创造特性需要继承Attribute,且名字后必须以Attribute结尾,使用时不需要Attribute结尾
public class CanSaveAttribute : System.Attribute
{//下面都是希望存在特性里的信息作者,版本号,和是否检查过public string author="";public string versionNumber="";public bool isCheck;
}

那我们该如何使用这个存档系统呢,拿我的模板当个实例,我需要存储玩家的位置信息和名字信息,我把模板项目的玩家控制代码发出来,挂到玩家上即可,看好注释哦,后面放游戏内容截图

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Player : MonoBehaviour
{public Rigidbody2D Rigidbody2D;public float speed = 10f;public SaveDataObject SObject;//先声明我们要存的对象public Text X;public Text Y;public Text Z;public Text NameUI;// Start is called before the first frame updatevoid Start(){Rigidbody2D=GetComponent<Rigidbody2D>();}// Update is called once per framevoid Update(){Rigidbody2D.velocity = new Vector2(Input.GetAxis("Horizontal") * speed, Input.GetAxis("Vertical") *speed);X.text = Convert.ToString(transform.position.x);Y.text = Convert.ToString(transform.position.y);Z.text = Convert.ToString(transform.position.z);}//要用button的事件链接这两个函数哦public void ClickSave(){Player player=GetComponent<Player>();//获得玩家对象SObject=new SaveDataObject(player,"LiLei");//嘿嘿偷懒,把名字写这里传了SaveSysteam.Save<SaveDataObject>(SObject);//保存实际就这一行,传入我们要存的对象即可}public void ClickLoad(){Player player = GetComponent<Player>();SObject = new SaveDataObject(player);SaveSysteam.Load<SaveDataObject>(SObject);//和保存的使用方法一样//下面就是把获得的数据传回到游戏中了transform.position = new Vector3(SObject.X,SObject.Y,SObject.Z);NameUI.text = SObject.playerName;Debug.Log("IsLoad");}}
//这是我要存储的类型获得玩家名称和位置信息
//想存别的东西就现创建一个类就行了,不用动存档系统的代码哦,方便吧
[CanSave(author = "小羊宝正", versionNumber = "版本1.1",isCheck =true)]
public class SaveDataObject
{public float X;public float Y;public float Z;public string playerName;public  SaveDataObject(Player player,string name){X = player.transform.position.x;Y = player.transform.position.y;Z = player.transform.position.z;playerName = name;}public SaveDataObject(Player player){X = player.transform.position.x;Y = player.transform.position.y;Z = player.transform.position.z;}
}

该放截图了,先让小球走几步(走到load按钮上)

然后点击save按钮 控制台发出消息

打开我们存的文件,看数据被存好了

然后我们关掉游戏,让小球回到原点

然后再次运行,再点击load按钮,看小球回到存档的位置了,并且被起名LiLei(李雷)

这就是使用方法了,我写的存档系统还不错吧,非常简便且灵活,其他功能大家可以自己探索(比如存档位,在此基础上更改都不难,虽然我设计了其他完整的功能,但是临近期末没精力写出来了,以后要是反响好我就补)

下面是答应大家的SaveSystem完整源代码,被注释的是之前写错懒得删的不影响使用

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System.IO;public class SaveSysteam
{public static void Save<T>(T obj){int N=0;string[]Data=new string[10];Type type = typeof(T);if (type.IsDefined(typeof(CanSaveAttribute), false)){CanSaveAttribute can=type.GetCustomAttribute<CanSaveAttribute>();FieldInfo[] fields = type.GetFields();Data[N] = can.author;N++;Data[N] = can.versionNumber;N++;foreach (FieldInfo field in fields){//field.GetValue(obiect);Data[N] = Convert.ToString(field.GetValue(obj));N++;// Debug.Log(field.GetValue(obj));}File.WriteAllLines(@"D:\\c#\\存档系统\\GameData.txt", Data);Debug.Log("IsSave");}else{Debug.LogError("你保存了一个不包含特性CanSaveAttribute的类,请检查保存的类是否符合规定");}}public static void Load<T>(T obj){int N = 0;Type type = typeof(T);if (type.IsDefined(typeof(CanSaveAttribute), false)){CanSaveAttribute can = type.GetCustomAttribute<CanSaveAttribute>();FieldInfo[] fields = type.GetFields();string[] Data = new string[10];Data = File.ReadAllLines(@"D:\\c#\\存档系统\\GameData.txt");if (Data[N] == can.author && Data[N+1]==can.versionNumber){N = N + 2;//PropertyInfo[] propertyInfos = type.GetProperties();foreach (FieldInfo field in fields){switch (Convert.ToString(field.FieldType)){case "System.Int32":field.SetValue(obj, Convert.ToInt32(Data[N]));break;case "System.Double":field.SetValue(obj, Convert.ToDouble(Data[N]));break;case "System.String":field.SetValue(obj, Data[N]);break;case "System.Single":field.SetValue(obj, Convert.ToSingle(Data[N]));break;case "System.Decimal":field.SetValue(obj, Convert.ToDecimal(Data[N]));break;}Debug.Log(Convert.ToString(field.FieldType));N++;}}else{Debug.LogError("现在的类与存储时的特性有所差异,可以查看文件中的原作者名字取得联系并修改");}}else{Debug.LogError("你加载了一个不包含特性CanSaveAttribute的类,请检查加载的类是否符合规定或存在");}}}
[AttributeUsage(AttributeTargets.Class)]
public class CanSaveAttribute : System.Attribute
{public string author="";public string versionNumber="";public bool isCheck;
}

自己设计的代码无论多烂,自己都觉得像诗一样美好,自己总会去回味。自己不是专业的程序,一开始只是一个叛逆的爱打游戏的少年。可能是为了做一个游戏,又或者是儿时的科普读物让我向往计算机,我走上了游戏制作人的道路,开始自学unity和C#,我走过好多弯路,无论人生还是学习编程的过程中,我失败无数次。也长大了对游戏不再那么痴迷,但是我对编程的热爱却没有减退,希望这篇文章能帮助向我一样的自学者。希望每位读者能从我这读到你需要的知识。感谢阅读,感谢您的认真观看。

新手向 使用C#自带方法制作unity存档系统(无插件)相关推荐

  1. [Unity存档系统]简单介绍Unity常见存档系统二JSON以及使用方法

    学习目标: 如果你和我同样苦恼于游戏相关的数据怎么存储与读取,那么不妨看看这个up主有关Unity存档系统的教程.[Unity] 存档系统 Part 1 | PlayerPrefs | Unity初学 ...

  2. 带你制作百词斩单词表读写插件

    上篇博文简单的介绍了一下Chrome插件,今天就与大家分享一下我做的这款有实际意义的插件吧. 做这款插件主要是用百词斩站点进行单词学习时,遇到的一点点闹心事儿.在单词表中不能听发音.也不能练习拼写.所 ...

  3. python带你制作随机点名系统,超级简单

    前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 在某些难以抉择得时候,我们经常要用外力来帮助我们做出选择 比如,课堂随机点名或面对活动需要人上台表演时等等场景 这个时候,有一个随机点名系统就非常好啦,毕 ...

  4. oc 画一个圆弧_UG建模一个蜗杆的方法,纯手工建模无插件

    上次我们画了一个蜗杆,今天就来建模一个涡轮模型,也是非常简单. 这次还是无尺寸的随意建模,做出这么一个涡轮,来看看建模方法吧! 1 首先在XY平面上绘制一个直径100的圆,上下拉伸10mm 2 对圆柱 ...

  5. Ubuntu 16.04系统实用插件安装方法

    Ubuntu 16.04系统实用插件安装方法 Ubuntu 16.04 系统实用插件安装方法链接 搜狗输入法 链接: https://blog.csdn.net/u010648921/article/ ...

  6. win10用html文件做壁纸,利用win10自带工具制作动态壁纸的简单方法

    微软在最强大操作系统利用win10自带工具制作动态壁纸的简单方法的详细介绍. 利用win10自带工具制作动态壁纸的简单方法: 把图片做成动态壁纸,总共分4步:1.准备素材,2.素材导入,3.调整效果, ...

  7. 计算机要学安装系统吗,新手学电脑系统安装,新手电脑系统安装的几种方法

    电脑系统怎么安装,对于新手来说有点迷茫,毕竟刚接触电脑系统,电脑系统安装的方法有很多,目前市面上电脑系统安装方法有光盘安装法.U盘安装法.硬盘安装法.一键重装安装法,那么新手电脑系统安装有几种方法呢? ...

  8. 新手做电商直播带货怎么和快递合作谈价格

    新手做电商直播带货怎么和快递合作谈价格达人带货一般怎样的合作模式?#达人带货 #直播带货 #红人 #百收网 跟快递谈价其实是有方法的,快递的价格不是说不能打下来,就是需要你们多一点点的心机.这个视频我 ...

  9. 网页代码扒ppt_用“扒片”的方法制作ppt

    龙源期刊网 http://www.qikan.com.cn 用 " 扒片 " 的方法制作 ppt 作者:朱洁兰 潘流俊 来源:<电脑知识与技术> 2018 年第 09 ...

最新文章

  1. 你是“10倍工程师”吗?这个事,​国外小伙伴们都快“吵”起来了
  2. tf.io.gfile.glob 遍历文件
  3. html中绝对定位的父级,父元素相对定位,子元素绝对定位
  4. 2021-03-20 数据挖掘算法—SVM算法 python
  5. OpenCV亚像素角点检测
  6. 神经网络python实例分类_Python使用神经网络进行简单文本分类
  7. 软键盘挡住EditText
  8. mysql文献综述_文献综述随笔(二十)
  9. Java程序员需要掌握哪些技能才能通过大公司的面试
  10. opensource项目_最佳Opensource.com:开放的组织文化
  11. 亚马逊AWS IoT
  12. C++内存泄漏的几种情况
  13. 组合数学及其应用——鸽巢原理
  14. css如何使图片在右下角,这个右下角折角用css怎么画出来?
  15. protel dxp 2004教程:如何自己创建原理图符号与元器件封装
  16. 关于报错:There is already ‘什么Controller‘ bean method的解决方法
  17. 原生JS实现弹幕效果
  18. 【戴师兄数分】excel基础操作——函数专题(个人笔记)
  19. 【Oracle】B-tree和函数索引
  20. 【总结】云集各大高校 — 数学建模经验分享(万字总结)

热门文章

  1. Fiddler2 下断点修改HTTP报文
  2. 亚马逊云科技亮相服贸会并发布在中国的第二个可再生能源项目;耀世星辉CheerCar正式接入腾讯车联系统 | 全球TMT...
  3. NFC之华为AIPASS认证:测试用例简介
  4. android 自定义 snackbar,自定义Toast以及玩转SnackBar
  5. 基于迁移学习的脑肿瘤自动检测研究与系统实现
  6. 官网下载MySQL安装包流程
  7. 十个常用网络密码的安全保护措施
  8. 关于智能相机的一些测试功能点的专有名字解释~
  9. cat6 万兆_CAT5E、CAT6和CAT6A在系统性能及网络应用上有什么区别?
  10. JMV内存hprof文件分析