Unity通过Json文件加载UI

本文介绍了在Unity3D中利用加载的Json文件数据动态加载UI面板的方法。包括将UI面板相关内容做成预制体、创建Json文件存放信息、编写多个脚本进行反序列化、存储数据等操作,最后实现点击任务弹出任务界面的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.我们懂得了如何加载Json文件里的数据,那么通过加载这些数据,我们可以做很多事情,例如加载装备信息或者其他的信息,今天我们用加载出来的信息去动态加载UI面板。

步骤:
①将下面关于UI面板的东西作为预制体,放在Resources文件下,方便我们动态加载。(canvas里的东西除了EventSystem留在Canvas,其他都分别做成预制体)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

②还是先创建一个json文件存放好需要的信息。结构为集合infoList里存放几个面版的类型和路径(在Resources文件下的路径)

{
"infoList":
[
{"panelTypeString":"Task",
  "path":"Task"
},
{
"panelTypeString":"canvas",
  "path":"Canvas"
},
{
  "panelTypeString":"ItemMessage",
  "path":"icon"
 },
 {
  "panelTypeString":"MainMenu",
  "path":"MainPanel"
 }
]
}

注意:写完一定要去百度检验格式,避免不必要的错误。

③接着创建一个脚本UIPanelType.cs,里面只有UI面板的类型

public enum UIPanelType
{
    MainMenu,
    Task,
    Shop,
    Bag,
    Skill,
    System,
    ItemMessage,
    canvas
}

④进行反序列化(即二进制转对象),需要创建一个脚本UIPanelInfo进行操作,该脚本需要实现序列化接口ISerializationCallbackReceiver;

// 进行反序列化
[Serializable]//一定要写,而且不能错
public class UIPanelInfo:ISerializationCallbackReceiver
{
[NonSerialized]//一定要写,而且不能错
//UI的类型
public UIPanelType uiPanelType;
//下面两项与json文件里的数据要一样,顺序也要一样,例如:"panelTypeString":"Skill"的panelTypeString
//存储Json里UI的类型的字符串
public string panelTypeString;
//存储Json里UI预制体路径的字符串
public string path;
//反序列之前调用
public void OnAfterDeserialize()
{
uiPanelType=(UIPanelType )Enmu.Parse(typeof(UIPanelType ),panelTypeString);
}
  //序列化之前调用该方法
public void OnBeforeSerialize()
{
}
}

在该脚本下再创一个类(UIPanelTypeJson),也可以另外创建一个脚本

[Serializable]
class UIPanelTypeJson
{
public List<UIPanelInfo> infoList;//C#中集合和json的集合名字要一致,且需要标记上上序列化
}

⑤再创建一个BasePanel脚本作为基类,让其他子类继承。
BasePanel暂时不写东西,子类也暂时不写
在这里插入图片描述
⑥接下来我们需要使用字典来存储各种数据,需要使用TryGetValue(),它需要传一个key值,和一个变量存储返回的信息。如果大量使用TryGetValue(),则需要创建大量的变量。所以我们要重新编写一个方法避免这种情况。需要新建一个静态类DictionaryExtend

// 扩张字典的方法
//根据Key获得value,如果得到直接返回value,得不到返回null
//this Dictionary<Tkey,Tvalue>dict表示要获取值的字典,其中dict表示的是谁来调用这个方法。
public static Tvalue TryGet<Tkey,Tvalue>(this Dictionary<Tkey,Tvalue>dict,Tkey key)
{
Tvalue value;
dict.TryGetValue(key,out value);
return value;
}

⑦接下来最重要的一个类,UIManager(管理类)负责将json数据导入,动态加载脚本等操作。

public class UIManager
{
//单例模式(防止创建多个该对象)
private static UIManager instance;
public static UIManager GetInstance
{
get
{
	if(instance==null)
	{
	instance=new UIManager();
	}
}
}
//加载Canvas面板
private GameObject canvasTransform;
    public GameObject CanvasTransform
    {
        get
        {
            if(canvasTransform==null)
            {
                string path = pannelPathDict.TryGet(UIPanelType.canvas);
                canvasTransform = GameObject.Instantiate(Resources.Load(path)) as GameObject;
                canvasTransform.name = path;
            }
            return canvasTransform;
        }
    }


//存储加载进来的json数据
private Dictonary<UIPanelType,string> pannelPathDict;
//存放生成后的UI面板
 private Dictionary<UIPanelType, BasePanel> panelDict;
 //用栈来存放已经显示出来的UI面板
  private Stack<BasePanel> panelStack;
 //构造私有化
    private UIManager()
    {
        ParseUIPanelTypeJson();
    }
    void ParseUIPanelTypeJson()
    {
    	  if(pannelPathDict==null)
    	  {
    	  pannelPathDict=new Dictionary<UIPanelType,string>();
    	  }
    	   //加载json文件,json文件在Resources文件中
	 TextAsset info=Resources.Load<TextAsset>("Json/UIPanelTypeJson");
	 
 	UIPanelTypeJson jonObj=JsonUtility.Fromjson<UIPanelTypeJson>(info.text);
  //将每个数据存储在字典中
  foreach (UIPanelInfo item in jsonObj.infoList)
        {
            pannelPathDict.Add(item.uiPanelType, item.path);

 }
 //加载面板并且返回对应的脚本类型
BasePanel GetPanel(UIPanelType panelType)
{
//判空,若为空则创建一个对象	
 if(panelDict==null)
 {
 panelDict=new Dictionary<UIPanelType,BasePanel>();
}
//从panelDict获取脚本,获取不到则证明没有加载面板
BasePanel pannel=paneDict.TryGet(panelType);

if(pannel==null)
{
//如果pannel为空,先获得面板的路径,之后加载它
string path=panelPathDict.TryGet(panelType);
if(path!=null)
{
//生成面板
GameObject instPanel=GameObject.Instantiate(Resources.Load(path))as GameObject;
//将面板设为Canvas的子物体,才能显示出来。
instPanel.transform.SetParent(CanvasTranfrom.transform,false);
instPanel.name=path;
//为该物体添加对应的脚本
AddScriptsCompent(panelType,instpanel);
//将面板类型和脚本存放到字典中
panelDict.Add(panelType,instPanel.GetComponent<BasePanel>());
return instPanel.GetComponent<BasePanel>();
}
else
{
//路径为空,证明没有该类型的面板,返回空
return null;
}

}
else
{
//证明已经有该面板,无需再加载。
return pannel;
}
}
//动态加载脚本
void AddScriptsCompent(UIPanelType panelType,GameObject panel)
{
switch(panelType)
{
	case UIPanelType.Bag:
		panel.AddComponent<BagPanel>();
		break;
	case UIPanelType.ItemMessage:
		panel.AddComponent<ItemMessagePanel>();
		break;
	case UIPanelType.MainMenu:
		panel.AddComponent<MainMenuPanel>();
		break;
	case UIPanelType.Shop:
		panel.AddComponent<ShopPanel>();
		break;
	case UIPanelType.Skill:
		panel.AddComponent<SkillPanel>();
		break;
	case UIPanelType.System:
		panel.AddComponent<SystemPanel>();
		break;
	case UIPanelType.Task:
		panel.AddComponent<TaskPanel>();
		break;
}
}

//将显示的面板压入栈中
public void PushPanel(UIPanelType uIPanelType)
{
//判空
	if(panelStack==null)
	{
	panelStack=new Stack<BasePanel>();
	}
	BasePanel panel=Getpanel(uIPanelType);
	//为了后面UI各种状态处理,将其压入栈
	panelSatck.push(panel);
}
 
}

⑧在之前的BasePanel的子脚本MainMenuPanel 中添加button事件监听

//面板上要有Button组件
private Button icon;
    void  Start()
    {
        icon = GameObject.Find("Canvas/icon/TaskButton").GetComponent<Button>();
        //lamda表达式调用有参函数
        icon.onClick.AddListener(() =>
        {
            testButton(UIPanelType.Task);
        });
    }
    //根据类型生成点击按钮后生成的面板
    void testButton(UIPanelType type)
    {
        UIManager.GetInstacne.PushPanel(type);
    }

最后创建一个脚本作为启动脚本 GameRoot

void Start()
    {
        
        UIManager.GetInstacne.PushPanel(UIPanelType.MainMenu);
        UIManager.GetInstacne.PushPanel(UIPanelType.ItemMessage);
    }

运行结果,点击任务后,弹出任务界面
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值