Los principiantes utilizan los propios métodos de C# para crear un sistema de archivo Unity (sin complementos)

Puramente original, casero.

Todavía soy un estudiante de secundaria, así que si no soy bueno en eso, indíquelo si hay alguna laguna.

Primero mostremos cómo es nuestro proyecto de demostración.

Descarga del archivo de ingeniería del proyecto de demostración

Más adelante se publicará un video tutorial detallado en la estación B (por lo que el artículo se revisará más adelante)

Si le resulta problemático, puede copiarlo directamente en el proyecto y usarlo.

(Todos los códigos fuente de SaveSystem se publicarán al final para que todos puedan copiarlos)

Puede almacenar objetos con campos de tipos de valores y tipos de cadenas comunes

El método de uso es SaveSystem.Save <tipo de objeto almacenado> (nombre del objeto de los datos almacenados);

La carga es SaveSystem.Load <tipo de objeto leído> (nombre del objeto de los datos leídos);

Es así de simple, siempre y cuando los campos de su clase sean tipos de valores y tipos de cadenas comunes.

Para tipos de valores poco comunes, consulte los comentarios sobre la función Cargar en mi artículo y simplemente agréguelos en la declaración de cambio.

Usa esto para guardar

(Nota: se requieren los espacios de nombres del sistema de uso, UnityEngine, System.Reflection, System.IO para su uso)

(Este método de archivo también se puede usar en otros lugares. Puede eliminar todas las declaraciones de depuración en el código sin usar UnityEngine)

(El sistema de archivo solo puede aceptar clases con el atributo [CanSave] agregado para evitar errores causados ​​por clases incompatibles que se guardan)

(Esta característica se agregó solo para que todos la verifiquen)

(En el tutorial se encuentran instrucciones de uso más detalladas)

Use la interfaz de usuario para mostrar cambios en nuestros datos y luego guarde y cargue los botones para implementar las funciones de lectura y archivado de archivos.

Cree un nuevo script SaveSystem, elimine la función Actualizar y la función Iniciar generadas automáticamente por el editor, escribamos la primera función Sava, escribiré comentarios para explicar cada objeto que los principiantes tal vez no conozcan (es lo suficientemente considerado)

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的类,请检查保存的类是否符合规定");
        }
    }
    
    
}

Esta es nuestra función Guardar. ¿No es relativamente simple? Entonces agreguemos la función Cargar a la clase SaveSystem.

//泛型老样子(不会有人没注意听讲吧)
 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的类,请检查加载的类是否符合规定或存在");
        }
    }

A continuación se muestra la tabla que acepté (la encontré en otro blog, pero no puedo encontrar el autor original, así que no puedo publicar el enlace. Gracias al autor por organizarlo)

(Si hay un error, consulte la documentación más reciente de Microsoft)

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

Luego tenemos que escribir sobre el hoyo que cavamos antes. Sí, son las características.

//哈哈哈,自定义特性上还要加特性,这个特性标明它是给类用的
[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 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");
    }

}
//这是我要存储的类型获得玩家名称和位置信息
//想存别的东西就现创建一个类就行了,不用动存档系统的代码哦,方便吧
[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#,我走过好多弯路,无论人生还是学习编程的过程中,我失败无数次。也长大了对游戏不再那么痴迷,但是我对编程的热爱却没有减退,希望这篇文章能帮助向我一样的自学者。希望每位读者能从我这读到你需要的知识。感谢阅读,感谢您的认真观看。

Supongo que te gusta

Origin blog.csdn.net/wsxybz/article/details/128486717
Recomendado
Clasificación