学习笔记——基于NGUI的UI框架(一)(总结方法有问题,已作废)

目前已经把场景搭建完毕,登录注册界面都已做好,整个场景大概分三个模块:UI根节点的UI Root_LogOnScene以及加上背景不变的部分,注册界面panReg,登录界面panLogOn
在这里插入图片描述

在这里插入图片描述

当加载这个场景时,首先应该加载UIRoot以及大背景不变的部分,再在这个基础之上,加载登录或者注册界面。
第一步将这三部分均设置为预制体(Prefab),UI Root_LogOnScene存放到
Resources/UIPrefab/UIScene目录下。注册界面panReg,登录界面panLogOn存放到Resources/UIPrefab/UIWindows目录下方便管理。
在这里插入图片描述
第二步将这三个组件在场景中删除,实现在切换场景中动态加载出来,所以需要做以下几个步骤
1.创建脚本SceneMgr,主要控制场景之间的切换
2.创建脚本LogOnSceneCtrl,功能是控制登录的场景中UI的加载,然后在场景中创建一个空物体重命名为LogOnSceneCtrl,将LogOnSceneCtrl脚本挂载到物体上。
3.点开脚本LogOnSceneCtrl进行编辑

public class LogOnSceneCtrl : MonoBehaviour {

    void Awake()
    {
        GameObject obj = Resources.Load("UIPrefab/UIScene/UI Root_LogOnScene") as GameObject;
        Instantiate(obj);
    }
}

点运行,就将UIRoot及背景加载出来了,但是这样有一个问题,一个游戏有很多的界面,如果每次加载一个界面都需要调用一次Resources且要输入很长的路径,然后再克隆出来,会显得很麻烦
4.所以再创建一个类ResourcesMgr,管理整个游戏中的资源加载,不需要挂载到任何物体上,且需要每个场景都能够调用以加载资源,所以需要设置成一个单例

public class ResourcesMgr
{
    private static ResourcesMgr instance;

    public static ResourcesMgr Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new ResourcesMgr();
            }
            return instance;
        }
    }
}

5.因为随着游戏的开发,像这种单例势必也会有很多,所以这里再创建一个专门的单例基类Singleton

/// <summary>
/// 单例
/// </summary>
/// <typeparam name="T">子类继承时候会传给单例一个类型,且要求实例化</typeparam>
public class Singleton<T> where T:new()
{
    private static T instance;
    public static T Instance
    {
        get
        {
            if(instance==null)
            {
                instance = new T();
            }
            return instance;
        }
        
    }
}

将ResourcesMgr继承单例类Singleton,这样ResourcesMgr自动有一个单例的属性

public class ResourcesMgr:Singleton<ResourcesMgr>
{
	
}

再在ResourcesMgr上面写方法,因为每次加载资源都需要写很长的路劲,为了应对这个问题,将路径简化,所以对资源类型进行分类,添加了一个menu,并对Load函数进行一定的调整

 using System.Collections;
using System.Text;
public class ResourcesMgr:Singleton<ResourcesMgr>
{
    #region ResourceType 资源类型
    /// <summary>
    /// 资源类型
    /// </summary>
    public enum ResourceType
    {
        /// <summary>
        /// 场景UI
        /// </summary>
        UIScene,
        /// <summary>
        /// UI窗口
        /// </summary>
        UIWindow,
        /// <summary>
        /// 角色
        /// </summary>
        Role,
        /// <summary>
        /// 特效
        /// </summary>
        Effect
    }
    #endregion
    #region Load 加载资源
    /// <summary>
    /// 加载资源
    /// </summary>
    /// <param name="type">资源类型</param>
    /// <param name="path">短路径(文件名)</param>
    /// <returns>预设克隆体</returns>
    public GameObject Load(ResourceType type,string path)
    {
        StringBuilder sbr = new StringBuilder();
        switch(type)
        {
            case ResourceType.UIScene:
                sbr.Append("UIPrefab/UIScene/");
                break;
            case ResourceType.UIWindow:
                sbr.Append("UIPrefab/UIWindows/");
                break;
            case ResourceType.Role:
                sbr.Append("RolePrefab/");
                break;
            case ResourceType.Effect:
                sbr.Append("EffectPrefab");
                break;
        }
        sbr.Append(path);        
        return Resources.Load(sbr.ToString) as GameObject;
    }
    #endregion
}

这样LogOnSceneCtrl就可以的方法就变成

public class LogOnSceneCtrl : MonoBehaviour 
{
    void Awake()
    {
        GameObject obj = ResourcesMgr.Instance.Load(ResourcesMgr.ResourceType.UIScene,"UI Root_LogOnScene");

        Instantiate(obj);
    }
}

6.现在已经实现了加载的一定简化,但是如果每次打开窗口都要进行创建或者销毁,会造成很大的资源的浪费,所以需要将已生成的资源放入缓存中,当要打开窗口是直接调用即可。在ResourcesMgr类中添加一个预设的哈希表,并实例化,每次创建资源的时候,判断是否哈希表是否有这个资源,有就直接加载,而不用再生成,代码如下:

public class ResourcesMgr:Singleton<ResourcesMgr>
{
    #region ResourceType 资源类型
    /// <summary>
    /// 资源类型
    /// </summary>
    public enum ResourceType
    {
        /// <summary>
        /// 场景UI
        /// </summary>
        UIScene,
        /// <summary>
        /// UI窗口
        /// </summary>
        UIWindow,
        /// <summary>
        /// 角色
        /// </summary>
        Role,
        /// <summary>
        /// 特效
        /// </summary>
        Effect
    }
    #endregion

    /// <summary>
    /// 预设的列表
    /// </summary>
    private Hashtable m_PrefabTable;

    /// <summary>
    /// 构造函数 实例化哈希表
    /// </summary>
    public ResourcesMgr()
    {
        m_PrefabTable = new Hashtable();
    }
    #region Load 加载资源
    /// <summary>
    /// 加载资源
    /// </summary>
    /// <param name="type">资源类型</param>
    /// <param name="path">短路径(文件名)</param>
    /// <param name="cache">是否放入缓存</param>
    /// <returns>预设克隆体</returns>
    public GameObject Load(ResourceType type,string path,bool cache=false)
    {
        StringBuilder sbr = new StringBuilder();
        switch(type)
        {
            case ResourceType.UIScene:
                sbr.Append("UIPrefab/UIScene/");
                break;
            case ResourceType.UIWindow:
                sbr.Append("UIPrefab/UIWindows/");
                break;
            case ResourceType.Role:
                sbr.Append("RolePrefab/");
                break;
            case ResourceType.Effect:
                sbr.Append("EffectPrefab");
                break;
        }
        sbr.Append(path);
        
        //当一个窗口被频繁的销毁或创建,势必为造成资源的浪费,所以需要将已经生成的窗口放入缓存中
        GameObject obj = null;
        if(m_PrefabTable.Contains(path))
        {
            Debug.Log("资源是从缓存中加载的"); 
            obj = m_PrefabTable[path] as GameObject;
        }
        else
        {
            obj= Resources.Load(sbr.ToString()) as GameObject;
            if(cache)
            {
                m_PrefabTable.Add(path, obj);
            }
        }
            
        return GameObject.Instantiate(obj);
    }
    #endregion
}

LogOnSceneCtrl调用方法为

    public class LogOnSceneCtrl : MonoBehaviour
     {
        void Awake()
        {
            GameObject  obj = ResourcesMgr.Instance.Load(ResourcesMgr.ResourceType.UIScene,"UI Root_LogOnScene",cache:true);
    
        }
  	 }

到这里就实现了,最开始的动态加载,后面会进一步简化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值