简单的UI框架 | 四、开发UIManager的单例和JsonUtlity调试

简单的UI框架

开发UIManager的单例和JsonUtlity调试




一、UIManager的单例

首先我们要知道什么是单例模式
单例模式是比较常见的一种设计模式,目的是保证一个类只能有一个实例,而且自行实例化并向整个系统提供这个实例,避免频繁创建对象,节约内存。
单例模式的核心:
1、定义一个静态的对象,在外部访问,在内部构造。
2、构造方法私有化。

private static UIManager _instance;

    public static UIManager Instance
    {
    
    
        get
        {
    
    
            if (_instance == null)
            {
    
    
                _instance = new UIManager();
            }
            return _instance;
        }
    }

标准的单例模式为上述代码,我们试着分析一下!
首先建立一个私有的静态变量 _instance
这个变量什么时候赋值呢,这时候我们定义一个get方法。
当变量为空的时候我们就创建一个。

    private UIManager()
    {
    
    
        ParseUITypeJson();
    }

UIManager是一个私有的构造方法,他只能在类的内部调用,所以在这里是可以构造的。
这样的话我们在外界只需要访问这个静态的方法就可以。
当我们第一次访问这个静态方法的时候,这个变量是为空的,这样他就会创建这个UIManager
这样在外界我们只需要UIManager.Instance就可以访问了,当我们在外面访问的时候,它就会自动构造访问ParseUITypeJson方法,就会去解析我们的Json文件。
这里面我们测试一下,我们建立一个测试方法:

  public void Test()
    {
    
    
        string path;
        panelPathDict.TryGetValue(UIType.Knapsack, out path);
        Debug.Log(path);
    }

然后我们新建一个脚本来调用这个方法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameRoot : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    void Start()
    {
    
    
        UIManager.Instance.Test();
    }
}

当我们通过UIManager访问这个Instance时,他就会执行Get方法,他就会调用UIManager方法,就会调用ParseUITypeJson方法自动解析Json文件,然后再调用Text方法的时候就会直接输出里面的信息。

我们回到Unity中运行一下
发现控制面板报错
在这里插入图片描述

发现是Json文件解析的时候出现错误,那我们接下来对JsonUtility进行调试。

二、JsonUtlity调试

既然我们的Json解析不了这个类型的,那么我们就不要让他解析了。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class UIPanelInfo
{
    
    
    [NonSerialized]
    public UIType panelType;
    public string path;
}

**[NonSerialized]**表示不去解析。
不去解析怎么办,我们就把他变成字符串类型的通过get set方法使用。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class UIPanelInfo
{
    
    
   [NonSerialized]
    public UIType panelType;
    public string panelTypeString
    {
    
    
        get 
        {
    
    
            return panelType.ToString();
        }
        set 
        {
    
    
            UIType type = (UIType)System.Enum.Parse(typeof(UIType), value);
            panelType = type;
        }
    }
    public string path;
}

把Json文件中的panelType全部改成panelTypeString。
现在只有
public string panelTypeString
public string path;

实现序列话和反序列化的过程。
我们怎么样字符串转化成枚举类型,我只需要这个类每次解析完之后转化一下即可。
我们就需要给他一个get set方法,get方法用来序列化,set方法用来反序列化。
序列化的时候我们只需要取值所以只需要return就可以了。
set方法我们需要把这个值转化为UIType类型的。
这里我们用要System.Enum中的Parse方法,Parse方法可以用来转换一个特点的类型,typeof我们需要取到要转化的类型,value就代表字符串,就是我们要转化的值。
枚举类型我们不能用as UIType来转换类型,我们就只能使用强制转换。

再运行的时候我们发现还是报错,那么我们使用另一种方式!
让我们的UIPanelType继承与一个接口

public class UIPanelInfo : ISerializationCallbackReceiver

Unity无法自动序列化Dictionary数据结构,解决思路是,我们将Dictionary的数据存储在可以序列化的结构里(如List),然后通过Dictionary与可序列化结构的互操作,来完成Dictionary的存储与加载,而这个互操作的时机,就是ISerializationCallbackReceiver接口的实现。
这个接口会自带两个构造方法:

    public void OnAfterDeserialize()
    {
    
    
        throw new NotImplementedException();
    }

    public void OnBeforeSerialize()
    {
    
    
        throw new NotImplementedException();
    }

第一个构造方法时反序列化之后调用这个方法。
第二个构造方法时序列化之前调用这个方法。
反序列化是指从文本信息到对象的过程。序列化与之相反。
我们每次要序列化的时候先把属性先更改一下调用OnBeforeSerialize()
序列化完成之后我们把文本转化成我们想要的枚举类型调用OnAfterDeserialize()
所以我们只需要将两个构造方法改成:

    public void OnAfterDeserialize()
    {
    
    
        UIType type = (UIType)System.Enum.Parse(typeof(UIType), panelTypeString);
        panelType = type;
    }

    public void OnBeforeSerialize()
    {
    
    

    }

将value改成panelTypeString,即我们要转化的值。

接下来我们再运行一下。
在这里插入图片描述
这样我们就运行成功了!

总结

今天我们学会了如何构造一个标准的单例模式,同时我们也学会了当Unity无法自动自动序列化的时候,我们可以对脚本更改的两种方法。

猜你喜欢

转载自blog.csdn.net/m0_64058685/article/details/124540994