新手向 使用C#自带方法弄一个unity存档系统无插件
纯原创,自制
本人还是个在校的高中生,能力不精如果有漏洞欢迎指出
先放出我们示范项目的样子
后面会在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,默认值为false
-
-
byte System.Byte
-
-
1Byte 8bit 无符号整数 无符号的字节,所存储的值的范围是0~255,默认值为0
-
-
sbyte System.SByte 1Byte
-
-
8bit 有符号整数 带符号的字节,所存储的值的范围是-128~127,默认值为0
-
-
char System.Char
-
-
2Byte 16bit 无符号Unicode字符,默认值为’\0’
-
-
-
decimal System.Decimal
-
-
16Byte 128bit十进制数不遵守四舍五入规则的十进制数,28个有效数字,通常用于财务方面的计算,默认值为0.0m
-
-
-
-
double System.Double
-
-
8Byte 64bit双精度的浮点类型,默认值为0.0d
-
-
float System.Single
-
-
4Byte 32bit单精度的浮点类型,默认值为0.0f
-
-
-
-
int System.Int32
-
-
4Byte 32bit有符号整数,默认值为0
-
-
uint System.UInt32
-
-
4Byte 32bit无符号整数,默认值为0
-
-
long System.Int64
-
-
8Byte 64bit有符号整数,默认值为0
然后我们要写之前挖的坑了,没错就是特性
-
//哈哈哈,自定义特性上还要加特性,这个特性标明它是给类用的
-
[]
-
//创造特性需要继承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 update
-
void Start()
-
{
-
Rigidbody2D=GetComponent<Rigidbody2D>();
-
-
}
-
-
// Update is called once per frame
-
void 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");
-
}
-
-
}
-
//这是我要存储的类型获得玩家名称和位置信息
-
//想存别的东西就现创建一个类就行了,不用动存档系统的代码哦,方便吧
-
[]
-
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的类,请检查加载的类是否符合规定或存在");
-
}
-
}
-
-
}
-
[]
-
public class CanSaveAttribute : System.Attribute
-
{
-
public string author="";
-
public string versionNumber="";
-
public bool isCheck;
-
}
自己设计的代码无论多烂,自己都觉得像诗一样美好,自己总会去回味。自己不是专业的程序,一开始只是一个叛逆的爱打游戏的少年。可能是为了做一个游戏,又或者是儿时的科普读物让我向往计算机,我走上了游戏制作人的道路,开始自学unity和C#,我走过好多弯路,无论人生还是学习编程的过程中,我失败无数次。也长大了对游戏不再那么痴迷,但是我对编程的热爱却没有减退,希望这篇文章能帮助向我一样的自学者。希望每位读者能从我这读到你需要的知识。感谢阅读,感谢您的认真观看。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhiabakc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
微信运动停用后别人还能看到步数吗
PHP中文网 07-22 -
excel打印预览压线压字怎么办
PHP中文网 06-22