Unity面向新手超简单的UI框架

前言

提醒:为了能够将知识点学得更加透彻、记得更加牢固 我会通过教学讲解的方式把知识写下来 因为在过程中会让人从学生变成老师 这个过程会挖掘出新的知识和观点 是一个自我思维切换而达成的知识深度挖掘和提升的过程 如果能帮助到大家那就最好 如果有讲错的地方还请多多指教!我只是一只菜鸡 感谢理解!


为什么要使用UI框架

游戏中存在非常多的面板 例如:背包面板、商店面板、设置面板、

这些面板之间会需要频繁的调用和切换,例如:背包面板中存在各种物品,我们鼠标放到物品上会出现物品信息的提示框,还有设置面板需要按返回键才可以切换回主菜单面板,那我们如何实现界面间的沟通呢?我之前的做法就是在每个我要用到的面板上都写一个脚本实现对应的功能,相信不少新手开发者都是这样过来的吧。(纳尼菜逼竟是我自己?)

虽然这样做功能是实现了,但是维护性降低了、重复的代码也变多了,为了更加方便的管理和调用场景中的面板 我们需要写一套完整的框架来对它们进行约束不然很容易出现面板共存,或者切换失败等问题。

恰好SIKI老师有一套面向新手的小型UI框架课程讲得蛮好的,最重要的是简单啊!!! 对我这种新手来说真的非常友好!我们一起来学习下吧!

框架的思路

先来简单介绍下这个框架的思路吧 ,框架主要实现了面板的读取存储和管理,帮助我们更好的进行面板之间的切换管理

首先

1、我们通过Json文件存储我们所有要用到的面板信息 例如:面板的名字 面板的类型 面板的加载路径 等等,按实际项目需求为准

2、创建一个面板抽象类(就是所有面板的基类)来实现面板共有的一些方法,比如面板进入的时候要做的一些事情,面板退出时候要做的一些事情

3、通过代码读取Json文件得到所有面板的信息,然后我们就能通过这些信息来操作面板

4、框架最核心的地方就是如何高效的管理这些面板 先来走一遍我们面板的生成和关闭的流程

Engelbart

此时玩家只能操作背包面板,无法操作人物面板(想想是不是很多游戏都是这样)当我们想要操作人物面板的时候 我们需要先关闭背包面板然后才能操作人物面板

这里再画一幅图来解释

现在我们位于最上面的设置菜单中子菜单界面,此时我们只能操作子菜单界面,如果我们想操作设置菜单界面的话 我们需要先关闭子菜单,才能操作设置菜单

Engelbart

现在子菜单关闭了,我们就可以操作设置菜单了!

Engelbart

同理如果我们想操作主菜单 那我们就必须要关闭设置菜单才能去操作主菜单

所以Siki老师是如何管理面板之间切换关系的呢?了解过数据结构的同学看了上面的图可能马上就懂了!对的就是用堆栈(Stack)来实现 ,堆栈是一个后进先出的对象集合 后进先出 先进后出?这不恰好可以用来存储管理我们的面板吗

先进后出 最先进入的是主菜单,所以我们把他放到了容器底部,然后玩家又点击了设置菜单,于是我们把他放到主菜单的上面,然后玩家又点击了设置菜单里的子菜单,我们把子菜单放到了设置菜单的上面

Engelbart

我们让玩家只能操作栈中的顶部面板,通过Push把面板入栈(面板进入) 通过Pop把顶部面板出栈(面板退出) 这样就轻松实现了面板之间的切换功能了

好吧说实话我觉得我讲的是一坨屎(可能只有我自己能听懂 推荐直接去看Siki老师讲的)


实操

思路理了一下!现在我们一步一步来做吧!

1、创建Json文件,把面板信息写入到Json中

首先我们来实现第一步

我们通过Json文件存储我们所有要用到的面板信息 例如:面板的名字 面板的类型 面板的加载路径 等等,按实际项目需求为准

在创建Json文件之前,我们需要先把要用到的面板做成预制体存放到Resources路径下稍后通过Resources来加载这些我们要用到的面板,这里我自己新建了一张图作为面板来演示,命名为“SettingPanel”存放到Resources的UIPanel文件夹下

Engelbart

好现在我们就来创建一个Json文件(新建一个文本文件 后缀改成.Json就是一个Json文件了,注意我们Json文件也要放到Resources文件夹下因为我们稍后会通过Resources来获取它) 并往里面写上我们面板的信息,这里为了方便小伙伴们的理解我就写简单一点

json文件

{
	"data":
	[
	   {"uiPanelType":"settingPanel","uiPanelPath":"UIPanel/SettingPanel"}
	]
}

这里简单讲下Json文件的格式吧

花括号{} 保存对象:对象可以包含各种数据,包括数组。
方括号[] 保存数组:数组可以包含对象。
数据由逗号分隔

不懂的我们可以直接找个在线解析Json的网站 这里推荐 https://www.bejson.com/convert/json2csharp/

我们直接选择Json转C#实体类看看 我们把写好的Json数据复制过去然后点击生成实体类看看

Engelbart

为了方便观察 我把生成的实体来复制过来给大伙看看

  
 public class DataItem
 {  
 	  public string uiPanelType { get; set; }
 
  	  public string uiPanelPath { get; set; }
 }

 public class Root
 {
     public List <DataItem> data { get; set; }
 }

不知道细心的小伙伴发现了没有 这两个类是不是刚好映射了Json文件里的数据

仔细对比一下 就能了解其中的意思

要注意的是 这些数据必须要和我们写的Json文件里的信息对应(反过来也是一样的 总之Json和映射类的信息名一定要保持一致) 只要写错一个单词 Json就会解析失败


//解析成功

public string uiPanelType { get; set; }
public string uiPanelPath { get; set; }
public List <DataItem> data { get; set; }

"uiPanelType":"settingPanel","uiPanelPath":"UIPanel/SettingPanel"}



//解析失败 映射类和Json的数据名称不一样 解析会报错

public string PanelType { get; set; }
public string PanelPath { get; set; }
public List <DataItem> paneldata { get; set; }

"uiPanelType":"settingPanel","uiPanelPath":"UIPanel/SettingPanel"}

我讲的可能跟一坨屎一样 甚至更差 (我帮你们讲了) 最好就是自己去度娘或者谷爹查下资料,现在我也就会最基本的操作回头我再深入学一下然后再写一篇关于Json的文章出来(祸害社会~)

刚刚是我们一键生成的映射类 现在我们自己动手来写下吧

PanelData类

public class PanelData
{
    /// <summary>
    /// UI面板类型
    /// </summary>
    public string uiPanelType;
    /// <summary>
    /// UI面板路径
    /// </summary>
    public string uiPanelPath;
}

UIPanelDataList类

public class UIPanelDataList
{
    public PanelData[] data;
}

两个映射类写完了 我们还要写一个UIPanelType枚举类 用来定义我们的面板类型,到时候我们拿到Json文件里的uiPanelType数据,然后将String转换成枚举类型就能得到面板的类型了

UIPanelType类:

public enum UIPanelType
{
     settingPanel           //设置面板
}

2、创建面板的基类

创建一个面板抽象类(就是所有面板的基类)来实现面板共有的一些方法,比如面板进入的时候要做的一些事情,面板退出时候要做的一些事情

UIPanelBase类比较简单 没什么好讲了 根据自己的需求定义面板共有的一些方法

UIPanelBase类:

using UnityEngine;

public class UIPanelBase : MonoBehaviour
{
    /// <summary>
    /// 入栈状态
    /// </summary>
    public virtual void PushState()
    {
        Debug.Log("入栈状态");
    }

    /// <summary>
    /// 出栈
    /// </summary>
    public virtual void PopState()
    {
        Debug.Log("出栈状态");
    }

    /// <summary>
    /// 面板恢复
    /// </summary>
    public virtual void RemotState()
    {
        Debug.Log("恢复状态");
    }
}

3、读取Json文件

通过代码读取Json文件得到所有面板的信息,然后我们就能通过这些信息来操作面板

这里我推荐使用LitJson,当然大家也可以用Unity自带的JsonUtility,哪个顺手就用那个。

要使用LitJson就需要去引用它 下载litJson.dll(这里我就不放下载链接了 Github上或者百度一下就有了) 放到Plugins文件夹下 如果没有就自己创建一个

Engelbart

现在我们可以创建核心的UIManager类

MainUIManager类

首先第一步引用litJson 非常简单就一句话 “using LitJson;”

然后把MainUIManager类做成一个单例(不懂单例的可以百度看看)


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

public class MainUIManager : MonoBehaviour
{
	/// <summary>
    /// MainUIManager单例
    /// </summary>
    public static MainUIManager Instance;
	
	public void Awake()
	{
		  Instance = this;
	}
}

单例做完后 我们需要两个字典 一个用来存储从Json解析出来的数据 另一个用来存储面板的UIPanelBase(我们需要在每个要操作的面板上添加一个脚本并继承UIPanelBase类 我们拿到面板身上的UIPanelBase类就相当于拿到了面板的实例)


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

public class MainUIManager : MonoBehaviour
{
	/// <summary>
    /// MainUIManager单例
    /// </summary>
    public static MainUIManager Instance;
	
	 /// <summary>
    /// 保存从Json文件解析出来的面板数据
    /// </summary>
    private Dictionary<UIPanelType, string> oriPanelDataDic = new Dictionary<UIPanelType, string>();
	
    /// <summary>
    /// 保存面板实例
    /// </summary>
    private Dictionary<UIPanelType, UIPanelBase> newPanelDataDic = new Dictionary<UIPanelType, UIPanelBase>();
	
	public void Awake()
	{
		  Instance = this;
	}
}

我英文不是太好 取名会有点差

现在我们就可以来读取Json文件里的数据了


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

public class MainUIManager : MonoBehaviour
{
	/// <summary>
    /// MainUIManager单例
    /// </summary>
    public static MainUIManager Instance;
	
	 /// <summary>
    /// 保存从Json文件解析出来的面板数据
    /// </summary>
    private Dictionary<UIPanelType, string> oriPanelDataDic = new Dictionary<UIPanelType, string>();
	
    /// <summary>
    /// 保存面板实例
    /// </summary>
    private Dictionary<UIPanelType, UIPanelBase> newPanelDataDic = new Dictionary<UIPanelType, UIPanelBase>();
	
	/// <summary>
    /// 文本资源 用于读取Json文件里的数据
    /// </summary>
    private TextAsset uiPanelJson;
	
	public void Awake()
	{
		  Instance = this;
	}
	
	 /// <summary>
    /// 初始化Json数据
    /// </summary>
    private void InitJson()
    {
        //获取Json文件数据
        uiPanelJson = Resources.Load<TextAsset>("UIPanelData");

		//解析Json
        UIPanelDataList panelData = JsonMapper.ToObject<UIPanelDataList>(uiPanelJson.text);

        //存储数据到字典中
        foreach (PanelData item in panelData.data)
        {
            //将String类型转换成枚举类型 并存储到字典中
			oriPanelDataDic.Add((UIPanelType)System.Enum.Parse(typeof(UIPanelType), item.uiPanelType.ToString()), item.uiPanelPath);
        }
    }
	
}

接下来我们拿到Canvas的Transform组件 等等我们写生成面板的逻辑需要把面板的父物体设置到Canvas下 Canvas我设置了个Tag 叫“UICanvas”所以我直接通过Tag去查找它


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

public class MainUIManager : MonoBehaviour
{
	/// <summary>
    /// MainUIManager单例
    /// </summary>
    public static MainUIManager Instance;
	
	 /// <summary>
    /// 保存从Json文件解析出来的面板数据
    /// </summary>
    private Dictionary<UIPanelType, string> oriPanelDataDic = new Dictionary<UIPanelType, string>();
	
    /// <summary>
    /// 保存面板实例
    /// </summary>
    private Dictionary<UIPanelType, UIPanelBase> newPanelDataDic = new Dictionary<UIPanelType, UIPanelBase>();
	
	/// <summary>
    /// 文本资源 用于读取Json文件里的数据
    /// </summary>
    private TextAsset uiPanelJson;
	
    private Transform uiCanvasTran;
	
	public void Awake()
	{
		  Instance = this;
		  InitJson();
          Init();
	}
	
	 /// <summary>
    /// 初始化Json数据
    /// </summary>
    private void InitJson()
    {
        //获取Json文件数据
        uiPanelJson = Resources.Load<TextAsset>("UIPanelData");

		//解析Json
        UIPanelDataList panelData = JsonMapper.ToObject<UIPanelDataList>(uiPanelJson.text);

        //存储数据到字典中
        foreach (PanelData item in panelData.data)
        {
            //将String类型转换成枚举类型 并存储到字典中
			oriPanelDataDic.Add((UIPanelType)System.Enum.Parse(typeof(UIPanelType), item.uiPanelType.ToString()), item.uiPanelPath);
        }
    }
	
	
	/// <summary>
    /// 初始化操作
    /// </summary>
    private void Init()
    {
        if (uiCanvasTran == null)
        {
            uiCanvasTran = GameObject.FindGameObjectWithTag("UICanvas").transform;
        }
    }
}

接下来写生成面板的逻辑 也是很简单的


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

public class MainUIManager : MonoBehaviour
{
	/// <summary>
    /// MainUIManager单例
    /// </summary>
    public static MainUIManager Instance;
	
	 /// <summary>
    /// 保存从Json文件解析出来的面板数据
    /// </summary>
    private Dictionary<UIPanelType, string> oriPanelDataDic = new Dictionary<UIPanelType, string>();
	
    /// <summary>
    /// 保存面板实例
    /// </summary>
    private Dictionary<UIPanelType, UIPanelBase> newPanelDataDic = new Dictionary<UIPanelType, UIPanelBase>();
	
	/// <summary>
    /// 文本资源 用于读取Json文件里的数据
    /// </summary>
    private TextAsset uiPanelJson;
	
    private Transform uiCanvasTran;
	
	public void Awake()
	{
		  Instance = this;
		  InitJson();
          Init();
	}
	
	 /// <summary>
    /// 初始化Json数据
    /// </summary>
    private void InitJson()
    {
        //获取Json文件数据
        uiPanelJson = Resources.Load<TextAsset>("UIPanelData");

		//解析Json
        UIPanelDataList panelData = JsonMapper.ToObject<UIPanelDataList>(uiPanelJson.text);

        //存储数据到字典中
        foreach (PanelData item in panelData.data)
        {
            //将String类型转换成枚举类型 并存储到字典中
			oriPanelDataDic.Add((UIPanelType)System.Enum.Parse(typeof(UIPanelType), item.uiPanelType.ToString()), item.uiPanelPath);
        }
    }
	
	
	/// <summary>
    /// 初始化操作
    /// </summary>
    private void Init()
    {
        if (uiCanvasTran == null)
        {
            uiCanvasTran = GameObject.FindGameObjectWithTag("UICanvas").transform;
        }
    }
}

    /// <summary>
    /// 生成面板
    /// </summary>
    /// <param name="panelType">面板类型</param>
    /// <returns></returns>
    public UIPanelBase GeneratePanel(UIPanelType panelType)
    {
        UIPanelBase uiPanelBase;
        newPanelDataDic.TryGetValue(panelType, out uiPanelBase);

        //如果uiPanelBase为空就表示没在字典中
        if (uiPanelBase == null)
        {
            string panelPath;
            oriPanelDataDic.TryGetValue(panelType, out panelPath);
            GameObject newPanel = Instantiate(Resources.Load<GameObject>(panelPath));
            newPanel.transform.SetParent(uiCanvasTran, false);
            uiPanelBase = newPanel.GetComponent<UIPanelBase>();
            newPanelDataDic.Add(panelType, uiPanelBase);
            return uiPanelBase;
        }
        return uiPanelBase;
    }

生成面板并返回得到uiPanelBase(面板基类)后我们就可以做面板入栈出栈的操作了


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

public class MainUIManager : MonoBehaviour
{
	/// <summary>
    /// MainUIManager单例
    /// </summary>
    public static MainUIManager Instance;
	
	 /// <summary>
    /// 保存从Json文件解析出来的面板数据
    /// </summary>
    private Dictionary<UIPanelType, string> oriPanelDataDic = new Dictionary<UIPanelType, string>();
	
    /// <summary>
    /// 保存面板实例
    /// </summary>
    private Dictionary<UIPanelType, UIPanelBase> newPanelDataDic = new Dictionary<UIPanelType, UIPanelBase>();
	
	/// <summary>
    /// 文本资源 用于读取Json文件里的数据
    /// </summary>
    private TextAsset uiPanelJson;
	
    private Transform uiCanvasTran;
	
	private Stack<UIPanelBase> panelStack;
	
	public void Awake()
	{
		  Instance = this;
		  InitJson();
          Init();
	}
	
	 /// <summary>
    /// 初始化Json数据
    /// </summary>
    private void InitJson()
    {
        //获取Json文件数据
        uiPanelJson = Resources.Load<TextAsset>("UIPanelData");

		//解析Json
        UIPanelDataList panelData = JsonMapper.ToObject<UIPanelDataList>(uiPanelJson.text);

        //存储数据到字典中
        foreach (PanelData item in panelData.data)
        {
            //将String类型转换成枚举类型 并存储到字典中
			oriPanelDataDic.Add((UIPanelType)System.Enum.Parse(typeof(UIPanelType), item.uiPanelType.ToString()), item.uiPanelPath);
        }
    }
	
	
	/// <summary>
    /// 初始化操作
    /// </summary>
    private void Init()
    {
        if (uiCanvasTran == null)
        {
            uiCanvasTran = GameObject.FindGameObjectWithTag("UICanvas").transform;
        }
    }


    /// <summary>
    /// 生成面板
    /// </summary>
    /// <param name="panelType">面板类型</param>
    /// <returns></returns>
    public UIPanelBase GeneratePanel(UIPanelType panelType)
    {
        UIPanelBase uiPanelBase;
        newPanelDataDic.TryGetValue(panelType, out uiPanelBase);

        //如果uiPanelBase为空就表示没在字典中
        if (uiPanelBase == null)
        {
            string panelPath;
            oriPanelDataDic.TryGetValue(panelType, out panelPath);
            GameObject newPanel = Instantiate(Resources.Load<GameObject>(panelPath));
            newPanel.transform.SetParent(uiCanvasTran, false);
            uiPanelBase = newPanel.GetComponent<UIPanelBase>();
            newPanelDataDic.Add(panelType, uiPanelBase);
            return uiPanelBase;
        }
        return uiPanelBase;
    }
	
	/// <summary>
    /// 面板入栈
    /// </summary>
    /// <param name="panelType"></param>
    public void PushPanel(UIPanelType panelType)
    {
        if(panelStack==null)
        {
            panelStack = new Stack<UIPanelBase>();
        }
        UIPanelBase uiPanelBase = GeneratePanel(panelType);
        uiPanelBase.PushState();
        panelStack.Push(uiPanelBase);
    }

    /// <summary>
    /// 面板出栈
    /// </summary>
    public void PopPanel()
    {
        if (panelStack == null) return;

        //拿到顶部数据
        UIPanelBase currentUIpanelBase = panelStack.Pop();
        currentUIpanelBase.PopState();

        if (panelStack.Count > 0)
        {
            UIPanelBase outUIpanelBase = panelStack.Peek();
            outUIpanelBase.RemotState();
        }
    }
}

这样我们的MainUIManager类就写完了 接下来调用就很简单了 我们为SettingPanel添加一个脚本“SettingPanel”(记得继承UIPanelBase)

public class SettingPanel : UIPanelBase
{
    public void AddButtonClick()
    {
        MainUIManager.Instance.PushPanel(UIPanelType.settingPanel);
    }
}

方法写好后 把他绑定到要点击的Button中(例如 点击设置按钮 显示设置面板 就把设置面板的脚本绑定到设置按钮的Button组件中)

Engelbart

啊不会绑定 直接把面板拖到OnClick上然后选择我们刚刚写的方法就好了 或者百度一下马上就懂了

现在我们所有的步骤都完成了 运行游戏看看效果吧!正常来说我们现在点击设置按钮就会弹出面板的了


4、最后

如果你弹出了面板 那就证明成功了,如果没弹出也不要灰心好好研究下代码看看报错,在上面的案例中我们只做了面板入栈的操作,你可以试着完成下面板出栈的操作,非常简单的只需要写一行代码就好了,写代码就是要思考为什么,而不是什么都跟着敲,试着自己在这套框架上添加一些新的功能吧!

最后还是要说明下 文章主要是用来巩固我学到的知识用的,所以没那些大佬讲的这么详细,要是把你看懵了!那我就非常抱歉了,建议关掉去看一遍完整的教程哈哈哈哈~

原文地址:https://blog.csdn.net/weixin_39356552/article/details/113462208

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍了Unity游戏开发中外观模式是什么意思,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家...
这篇文章主要介绍Unity中地面检测方案的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.普通射线在角色坐标(一般是脚底)...
这篇文章主要介绍了Unity游戏开发中如何消除不想要的黄色警告,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带...
这篇文章主要介绍了Unity中有多少种渲染队列,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解
这篇文章主要介绍Unity中如何实现Texture,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!了解Texture2D 如上图,Texture2D是一张
小编给大家分享一下Unity中DOTS要实现的特点有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让...
这篇文章给大家分享的是有关unity中如何实现UGUI遮罩流光特效的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。下面是核心shader:Sh...
这篇文章主要为大家展示了“Unity中如何实现3D坐标转换UGUI坐标”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下...
这篇文章主要介绍了Unity游戏开发中设计模式的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家...
这篇文章主要介绍了Unity中如何实现仿真丝袜渲染,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了...
这篇文章给大家分享的是有关Unity插件OVRLipSync有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。项目需要接入对话口型动...
这篇文章主要介绍了Unity性能优化之DrawCall的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家...
这篇文章给大家分享的是有关Unity给力插件之Final IK怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。这插件有什么用:一般游...
这篇文章给大家分享的是有关Unity中如何内嵌网页插件UniWebView的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、常见Unity中内...
小编给大家分享一下Unity如何做流体物理的几个轮子,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让...
小编给大家分享一下Unity中Lod和Occlusion Culling的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收...
这篇文章将为大家详细讲解有关Unity中LineRenderer与TrailRenderer有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获...
这篇文章主要介绍了Unity中coroutine问题的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起...
这篇文章将为大家详细讲解有关unity中spine怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。骨骼动画首先我们来看到...
这篇文章主要为大家展示了“Unity Shader后处理中如何实现简单均值模糊”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学...