Unity程序基础框架学习笔记

Unity的程序基础框架,视频地址:https://www.bilibili.com/video/BV1C441117wU
一、建立目录
在Assets下建立标准目录,如下图:
在这里插入图片描述
在这里插入图片描述
二、功能模块
在这里插入图片描述

三、脚本
3.1、单例模式基类
知识点:单例模式是设计模式中很常用的一种模式,它的目的是让一个类在程序运行期间有且只有一个实例。因为只有一个实例,减少了内存消耗和系统性能开销。单例模式有三个特点:
(1)单例类只能有一个实例。
(2)单例类必须自己创建自己的唯一实例。
(3)单例类必须给所有其他对象提供这一实例。
脚本:BaseManager.cs

//定义单例模式基类,采用泛型构造,使用无参构造函数约束泛型T的类型。
public class BaseManager<T> where T:new()
{
   
    //定义单例模式基类实例变量
    private static T instance;
    //定义单例模式基类中实例化方法
    public static T GetInstance()
    {
   
        //如果实例为空,则实例化对象
        if (instance == null)
            instance = new T();
        return instance;
    }
}

//------------------------------------------------------------------------------------

//单例模式基类的使用,新的单例模式类直接继承基类
public class GameManager : BaseManager<GameManager>
{
   

}
public class ItemManager : BaseManager<ItemManager>
{
   

}
//其他单例模式类的使用
public class test
{
   
    void main()
    {
   
        GameManager.GetInstance();
        ItemManager.GetInstance();
    }
}

3.2、缓存池模块
在GameObject大量生成->销毁的情况下(如子弹射击),销毁的物体只是删除对内存空间的引用,但并未释放实例化物体占用的内存空间。当内存空间占满后进行GC(Garbage Collection),将造成游戏运行卡顿。为了避免这种情况,通过缓存池对销毁物体的内存空间进行暂存,当需要创建新物体时直接从缓存池取出,新物体不再占用新的内存空间(除非缓存池中存放的物体数量不够),从而减少内存的消耗。
知识点:命名空间System.Collections.Generic中有两个非常重要,而且常用的泛型集合类,它们分别是Dictionary<TKey,TValue>字典和List列表。Dictionary字典通常用于保存键/值对的数据,而List列表通中用于保存可通过索引访问的对象的强类型列表。
脚本:PoolMgr.cs

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

public class PoolMgr : BaseManager<PoolMgr>
{
   
    //定义构造类,每类放入缓存池的物体应当有一个标识其类别的父对象,及存储物体的容器
    public class PoolData
    {
   
        public GameObject PoolFather;
        public List<GameObject> PoolList;
        //FObj物体用于在缓存池内表明物体具体类别,PoolObj物体用于代表缓存池,多个FObj的父对象都设置为PoolObj以体现层级关系
        public PoolData(GameObject Obj,GameObject PoolObj)
        {
   
            PoolFather = new GameObject(Obj.name);
            PoolFather.transform.parent = PoolObj.transform;
            PoolList = new List<GameObject>() {
    };
            PutObj(Obj);
        }
        public void PutObj(GameObject Obj)
        {
   
            Obj.SetActive(false);
            PoolList.Add(Obj);
            Obj.transform.parent = PoolFather.transform;
        }
        public GameObject GetObj()
        {
   
            GameObject Obj = null;
            Obj = PoolList[0];
            PoolList.RemoveAt(0);
            //取出物体时使其激活
            Obj.SetActive(true);
            //取出缓存池的物体断开和缓存池物体的父子联系
            Obj.transform.parent = null;
            return Obj;
        }
    }
    //创建缓存池,定义字典参数PoolDict实现多个对象的存储,其中第一个string参数说明缓存物体的类别,用自定义的PoolData类型作为第二个参数存储对象类别(PoolFather)和对象List列表(PoolList)。
    public Dictionary<string, PoolData> PoolDict = new Dictionary<string, PoolData>();
    //定义一个物体,放入缓存池中的物体挂接到该物体下面,实现界面的简介易懂
    private GameObject PoolObj;
    //把物体放入缓存池,第一个参数存储物体名字,第二个参数存储物体实例      
    public void PutObj(string name,GameObject Obj)
    {
   
        //如果缓存池物体为空,则创建一个
        if (PoolObj == null)
            PoolObj = new GameObject("Pool");
        //如果缓存池中有此类物体的List,则添加进该类物体的List中;如缓存池中无此类物体,则新建一个此类物体的List,并将该物体存入新建的List。
        if (PoolDict.ContainsKey(name))
        {
   
            //在对应name类的List中存入物体
            PoolDict[name].PutObj(Obj);
        }else 
        {
   
            //新建一个name类的PoolData,并把Obj物体添加进PoolData的List里
            PoolDict.Add(name, new PoolData(Obj,PoolObj));
        }
    }   
    //采用异步加载方式从缓存池中取出指定物体,通过物体名字进行索引
    public void GetObj(string name,UnityAction<GameObject> CallBack)
    {
   
        //如果缓存池中存在指定的物体名,且该类物体数量大于0则取出,否则重新实例化一个物体
        if (PoolDict.ContainsKey(name) && PoolDict[name].PoolList.Count > 0)
        {
   
            CallBack(PoolDict[name].GetObj());
            //调用PoolData中的GetObj()方法,从缓存池中取出物体
            //Obj = PoolDict[name].GetObj();
        }
        else
        {
   
            ResourcesMgr.GetInstance().LoadAsync<GameObject>(name,(PObj)=>
            {
   
                PObj.name = name;
                CallBack(PObj);
            });
            //重新实例化要取出的物体,从Resources目录中调用预制体
            //Obj = GameObject.Instantiate(Resources.Load<GameObject>(name));
            //把实例化的物体名字改为传入的调用名字,否则物体实例化后会在名字后面加上(clone),不利于后续处理
            //Obj.name = name;
        }
    }
    //切场景的时候应当清除缓存池并把缓存池物体置空,否则调用会报错
    public void PoolClear()
    {
   
        PoolDict.Clear();
        PoolObj = null;
    }
}

// PoolGetTest .cs----------------------------------------------------------------------
//从缓存池中取出物体脚本。当按下鼠标左键时,从缓存池取出指定名称为"Test/ Monster "的物体,当缓//存池中没有物体时,将从取出Resources/Test/目录下的Cube预制体进行实例化。按下鼠标右键时,则对"Test/ Player "物体进行相同操作。

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

public class PoolGetTest : MonoBehaviour
{
   
    void Update()
    {
   
        if(Input.GetMouseButtonDown(0))
        {
   
            PoolMgr.GetInstance().GetObj("Test/Monster",(Obj)=> {
    });
        }
        if (Input.GetMouseButtonDown(1))
        {
   
            PoolMgr.GetInstance().GetObj("Test/Player", (Obj) => {
    });
        }
    }
}

// PoolPutTest .cs----------------------------------------------------------------------
//将物体放入缓存池脚本。将此脚本挂在Resources/Test/目录下的预制体上,当该物体被实例化调用后,延迟1秒后放入缓存池。

public class PoolPutTest : MonoBehaviour
{
   
    //当对象激活时,会进入的生命周期函数
    private void OnEnable()
    {
   
        Invoke("Put",1);
    }
    void Put()
    {
   
        PoolMgr.GetInstance().PutObj(this.gameObject.name,this.gameObject);
    }
}

3.3、事件中心模块
通过Dictionary<string,UnityAction>存储事件及对应的处理方法,string存储事件名,UnityAction使用委托来存储多个事件处理方法。
脚本:EventMgr.cs

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

public class EventMgr : BaseManager<EventMgr>
{
   
    //Dictionary的Key对应字符串类型的事件名(如怪物死亡,玩家死亡等),Value对应的是监听这个事件的委托函数们,此处使用UnityEngine.Events命名空间下自带的事件标识UnityAction。
    private Dictionary<string, UnityAction<object>> EventDict = new Dictionary<string, UnityAction<object>>();
    
    //添加事件监听,添加指定事件名字的监听器,并说明准备处理该事件的方法
    public void AddEventListener(string name,UnityAction<object> action)
    {
   
        //如果事件管理模块中有name名字的事件,则在该事件中加入一个传入的处理方法
        if(EventDict.ContainsKey(name))
        {
   
            EventDict[name] += action;
        }
        //如果事件管理模块中没有name名字的事件,则添加这个事件以及对应的处理方法
        else 
        {
   
            EventDict.Add(name, action);
        }       
    }
    //移除事件监听,当物体销毁时应当在事件管理器中移除该物体监听事件执行的方法
    public void RemoveEventListener(string name,UnityAction<
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值