当前位置:   article > 正文

Unity基本框架_游戏开发框架为unitybaseframe(unity基础框架),该框架包含了以下类:

游戏开发框架为unitybaseframe(unity基础框架),该框架包含了以下类:

Unity 基础框架

本框架是我从github上clone下的,只能算是自己一些理解
若,若是侵权请联系我删除,若是有错误请指出

原项目地址

基础框架简介

本框架包含了以下类

BaseManager、BasePanel、EventCenter、InputMgr、MonoController、MonoMger、MusicMgr、PoolMgr、ResMgr、UIManager

框架的作用便是协助开发,提升开发效率,但也不能一味的使用框架丧失了新功能的开发,不断学习,对自己的框架进行更行是程序员必须做的,下面我们就开始简单介绍这些框架

BaseManager

最基础的类,大部分的类继承于它

此类为单例模式,项目中所有的使用单例模式的类都继承于它,并且此类使用了泛型,将大大减少重复性代码的出现

相信大家对单例模式都不陌生,就不注重细说了

//使用where对泛型T进行约束
public class BaseManager<T> where T:new()
{
  private static T instance;
    //静态函数,建T的实体instance

  public static T GetInstance()
  {
    if (instance == null)
      instance = new T();
    return instance;
  }
   //返回这个类的实体instance
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

MonoController

因为我们大部分类都继承自了BaseManager,而BaseManager没有继承MonoBehaviour,所以在这些类中我们无法使用Unity为我们提供的周期函数,所以我们定义了一个MonoController类让它实现周期函数

此框架为基本框架,如有需要亦可修改使用

public class MonoController : MonoBehaviour
{

    //设置事件,用此事件监听需要循环更新执行的函数
    private event UnityAction updateEvent;
    private event UnityAction fixedUpdateEvent;

    //此物体不可移除
    private void Start()
    {
        DontDestroyOnLoad(this.gameObject);
    }
	//如果此事件不为空,则在此类的Update里调用
    private void Update()
    {
        if (updateEvent != null)
            updateEvent();
    }
	//随时间更行的调用
    private void FixedUpdate()
    {
        if (fixedUpdateEvent != null)
            fixedUpdateEvent();
    }

    //对方法添加监听
    public void AddUpdateListener(UnityAction func)
    {
        updateEvent += func;
    }

    //移除
    public void RemoveUpdateListener(UnityAction func)
    {
        updateEvent -= func;
    }

    public void AddFixedUpdateListener(UnityAction func)
    {
        fixedUpdateEvent += func;
    }

    public void RemoveFiUpdateListener(UnityAction func)
    {
        fixedUpdateEvent -= func;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

MonoMgr

在拥有了MonoController后,我们需要解决的就是对MonoController的使用问题了,为此我们需要创建一个管理类MonoMgr,将此类继承自BaseManager做成单例模式,这样我们便能方便的调用MonoController了

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

public class MonoMgr : BaseManager<MonoMgr>
{
    //为了能够使用并管理MonoController,我们首先需要一个MonoController对象
    private MonoController controller;
	
    //由于是单例模式,我们创建构造函数来进行一些必要的初始化
    public MonoMgr()
    {
        //MonoController并不是单例模式,为了使用我们要让它在游戏中生成,首先新创建一个游戏物体名为MonoController
        GameObject obj = new GameObject("MonoController");
        //挂载脚本,并获得此脚本的引用controller
        controller = obj.AddComponent<MonoController>();
    }
	//调用controller里的添加监听的方法,注意传入的参数为无参无返回值的方法
    public void AddUpdateListener(UnityAction func)
    {
        controller.AddUpdateListener(func);
    }
	//同上,不过此方法针对的是随时间更新
    public void AddFixUpdateListener(UnityAction func)
    {
        controller.AddFixedUpdateListener(func);
    }
	//移除监听在Update里的方法
    public void RemoveUpdeteListener(UnityAction func)
    {
        controller.RemoveUpdateListener(func);
    }
    //同上移除监听在FixUpdater的方法
    public void RemoveFixUpdateListener(UnityAction func)
    {
        controller.RemoveFiUpdateListener(func);
    }

	//开启协程方法及其重载方法,使用时注意选择
    public Coroutine StartCoroutine(IEnumerator routine)
    {
        return controller.StartCoroutine(routine);
    }

    public Coroutine StartCoroutine(string methodName, [DefaultValue("null")] object value)
    {
         return controller.StartCoroutine(methodName, value);
    }

    public Coroutine StartCoroutine(string methodName)
    {
        return controller.StartCoroutine(methodName);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

ResMgr

资源加载类,通过Resource文件夹进行资源的加载
需要注意一点,此时加载出来的物体的this.name都会成为原名加上(clone)
所以在使用缓存池PoolMgr.PushObj时谨慎使用this.name

//单例模式继承自BaseManager,使用时可以通过GetInstance调用
public class ResMgr : BaseManager<ResMgr>
{
    //同步加载
    //使用是要注意给出T的类型,如ResMagr.GetInstance().Load<GameObject>()
     public T Load<T>(string objName) where T : Object
    {
        T res = Resources.Load<T>(objName);
        //如果res是一个GameObject
        if (res is GameObject)
        {
           T t = GameObject.Instantiate(res);
           t.name = objName;
           return t;

        }
        else //else情况示例:TextAsset、AudioClip
            return res;
    }
    //异步加载,异步加载使用起来在观感上更加顺滑,适用于较大的资源
    //异步加载使用协程
    public void LoadAsync<T>(string name, UnityAction<T> callback) where T : Object
    {
        //由于是单例模式,要使用协程需要用到MonoMgr
        MonoMgr.GetInstance().StartCoroutine(ReallyLoadAsync<T>(name, callback));
    }
	
    private IEnumerator ReallyLoadAsync<T>(string _name, UnityAction<T> callback) where T : Object
    {
        ResourceRequest r = Resources.LoadAsync<T>(name);
        yield return r;//直到系统读取完
        if (r.asset is GameObject)
        {
          T t = GameObject.Instantiate(r.asset) as T;
            t.name = _name;//去点(clone)字段
            callback(t);//callback方法作用很大,例如获得其组件脚本,改变其状态        
        }
            
        else
            r.asset.name = _name;
            callback(r.asset as T);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

PoolMgr

缓存池系统。系统频繁生成物体和销毁物体是很浪费性能的,为此我们可以将暂时用不到的物体使用SetActive(false)来隐藏掉,并将他们存入缓存池,在需要使用时在取出

public class PoolData
{
    
    //缓存池中可能有多个不同种类的物体,为方便管理故需要设置一个父物体
    public GameObject fatherObj;
    //使用List链式结构来存储物体
    public List<GameObject> poolList;

    //构造函数,进行PoolData的一些初始化
    public PoolData(GameObject obj,GameObject poolObj)
    {
        fatherObj = obj;
        fatherObj.transform.parent = poolObj.transform;
        poolList = new List<GameObject>();
        PushObj(obj);
        
    }
	//将物体push进缓存池
    public void PushObj(GameObject obj)
    {
        //存储、设置父物体、隐藏
        poolList.Add(obj);
        obj.transform.SetParent(fatherObj.transform);
        obj.SetActive(false);
    }
	//将物体从缓存池取出
    public GameObject GetObj()
    {
        GameObject obj = null;
        obj = poolList[0];
        poolList.RemoveAt(0);
        obj.SetActive(true);
        obj.transform.parent = null;
        return obj;
    }
}

//缓存池定义完成,我们需要一个对缓存池进行管理的单例模式类
public class PoolMgr : BaseManager<PoolMgr>
{
    //使用字典存储数据
    private Dictionary<string, PoolData> poolDic
        = new Dictionary<string, PoolData>();
	//缓存池的父物体
    private GameObject poolObj;
	
    //从缓存池中取出
    public void GetObj(string objName, UnityAction<GameObject> callback)
    {
        //若缓存池中存在,取出
        if (poolDic.ContainsKey(objName) && poolDic[objName].poolList.Count > 0)
            callback(poolDic[objName].GetObj());
        //若不存在则使用ResMgr动态加载
        else
        {
        //注意生成的物体的this.name此时并不是objName,而是objName(clone),若是使用this.name进行PushObj的话,则无法使用objName从字典中进行Get
           ResMgr.GetInstance().LoadAsync<GameObject>(objName,callback);
           
        }
    }
	//将物体存如缓存池
	//使用时注意objName,使用动态加载出来的物体的this.name会在原名后加上(clone)字样,此时使用this.name进行PushObj操作时,实际是创建了另一个池子,所以使用时推荐直接使用"objName"的方式而不是this.name的方式
    public void PushObj(string objName, GameObject obj)
    {
        if (poolObj == null)
            poolObj = new GameObject("Pool");//实例化,此后所以在缓存池的物体全部为其紫萼u提
        if(poolDic.ContainsKey(objName))//如果缓存池中已经存在其类型,则将物体加入其中
            poolDic[objName].PushObj(obj);
        else//若缓存池中没有此类物体,则添加至字典
            poolDic.Add(objName,new PoolData(obj,poolObj));
         //我们采用的就结构是PoolData 类,里面含有链式结构PoolList 
    }
	//清空缓存池
    public void Clear()
    {
        poolDic.Clear();
        poolObj = null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

EventCenter

事件中心,通过事件我们来解决各个函数的运行问题,减少脚本的耦合性,是结构桁架美观

事件系统的构成主要依赖于委托,委托没有学号的小伙伴最好先去学习下

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
//两个类使用此接口,可用此接口来调用对象,可使用as判断
public interface iEveninfo
{
    
}
//创建类继承自接口,以后便可以通过接口来引用此类
public class EventInfo<T> : iEveninfo
{
    //注意参数名actions,多加了一个S,此委托监听多个函数
    public Action<T> actions;
	
    //action,将要监听的函数
    public EventInfo(Action<T> action)
    {
        actions += action;
    }
}
//同上,不过此时的委托为无参委托
public class EventInfo : iEveninfo
{
    public Action actions;

    public EventInfo(Action action)
    {
        actions += action;
    }
}

//事件系统为单例模式,继承自BaseManager
public class EventCenter : BaseManager<EventCenter>
{
    //使用字典结构,可以方便的通过“name"来触发委托,注意此时用的是接口
    public Dictionary<string, iEveninfo> eventDic
        = new Dictionary<string, iEveninfo>();

    //添加监听,注意监听的函数为带参函数
    public void AddEventListener<T>(string eventNumber, Action<T> action)
    {
        //如果字典中已经有此eventNumber,将此方法添加至字典中
        if (eventDic.ContainsKey(eventNumber))
            (eventDic[eventNumber] as EventInfo<T>).actions += action;//使用as来转换,此时接口转化成了EventInfo<T>
        //若没有此eventNumber,则在字典中添加事件名和事件方法
        else 
            eventDic.Add(eventNumber,new EventInfo<T>(action));
    }
	//添加监听,同上不过方法无参数
    public void AddEventListener(string eventNumber, Action action)
    {
        if (eventDic.ContainsKey(eventNumber))
            (eventDic[eventNumber] as EventInfo).actions += action;
        else
            eventDic.Add(eventNumber,new EventInfo(action));
    }
	//触发监听的事件,由于存在泛型T,及我们的所监听的函数需要一个类型为T的参数才能触发
    public void EventTrigger<T>(string eventNumber, T info)
    {	
        //如果字典里存在此事件并且actions不为空
        if(eventDic.ContainsKey(eventNumber)&& 
           (eventDic[eventNumber] as EventInfo<T>).actions!=null
           )
            (eventDic[eventNumber] as EventInfo<T>).actions.Invoke(info);
        
    }
	//同上,但不需要参数
    public void EventTrigger(string eventNumber)
    {
        if (eventDic.ContainsKey(eventNumber)&&
            (eventDic[eventNumber] as EventInfo).actions != null)
            (eventDic[eventNumber] as EventInfo).actions.Invoke();
    }
	//移除监听
    public void RemoveEventListener<T>(string eventNumber, Action<T> action)
    {
        if (eventDic.ContainsKey(eventNumber))
            (eventDic[eventNumber] as EventInfo<T>).actions -= action;
    }
	//如上,移除监听
    public void RemoveEventListener(string eventNumber, Action action)
    {
        if (eventDic.ContainsKey(eventNumber))
            (eventDic[eventNumber] as EventInfo).actions -= action;
    }
	//清空字典
    public void Clear()
    {
        eventDic.Clear();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

InputMgr

输入系统,我们的对键盘鼠标的操作都可以在此进行定义,由于我们的操作要实时检测输入,所以在定义InputMgr时我们要使用到前面的MonoMgr

Unity2020版本 推出了新的Input System,有兴趣的小伙伴可以去学习,本文暂且不表

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

//继承自BaseManager
public class InputMgr : BaseManager<InputMgr>
{
   //输入开关
  private bool isStart = false;
  private float timer;

    //构造函数,对设置初始化
  public InputMgr()
  {
      
    MonoMgr.GetInstance().AddUpdateListener(MyUpDate);//帧更新,应该设置时间更新
    MonoMgr.GetInstance().AddFixUpdateListener(MyFixUpdate);
  }

  public void StartOrEndCheck(bool isOpen)
  {
    isStart = isOpen;
  }

  private void MyUpDate()
  {
    if(!isStart)
      return;
      //在其中可设置你需要的输入方式,以下是我自己的定义
    FindMousePoint();//找到鼠标的点,并实现事件
    CheckHMove();//鼠标WS实现上下移动
    CheckVMove();//鼠标AD实现左右移动
  	ChecKKeyCode(KeyCode.J)//实现按下J的事件监听
 
  }

//随时间更新
  void MyFixUpdate()
  {
    if(!isStart)
      return;
    CheckMouseClick(0.12f);
  }

  
  
//检测鼠标输入
  void CheckMouseClick(float t)
  {
    timer += Time.deltaTime;
    if (Input.GetMouseButton(0) && timer >= t)
    {
      EventCenter.GetInstance().EventTrigger("Fire");
      timer = 0;
    }
        
  }

  //鼠标输入,得到点击的位置
  void FindMousePoint()
  {
  
      Vector3 point = Input.mousePosition;
      point.z = -10;
      point = Camera.main.ScreenToWorldPoint(point);
   
      Debug.Log(point);
      EventCenter.GetInstance().EventTrigger("FindMousePoint", point);
  }
    //检测WS键,执行VMove事件
  public void CheckVMove()
  {
    float v = Input.GetAxisRaw("Vertical");//对于WS
    
    EventCenter.GetInstance().EventTrigger("VMove",v);
  }
	//检测AD键,执行HMove事件
  public void CheckHMove()
  {
    float h = Input.GetAxisRaw("Horizontal");//对于AD
    EventCenter.GetInstance().EventTrigger("HMove",h);
  }
	//检测键盘输入,根据按压类别启动不同事件
  public void CheckKeyCode(KeyCode key)
  {
    if (Input.GetKeyDown(key))
      EventCenter.GetInstance().EventTrigger("KeyIsDown",key);
    if(Input.GetKey(key))
      EventCenter.GetInstance().EventTrigger("KeyAlwaysDown",key);
    if(Input.GetKeyUp(key))
      EventCenter.GetInstance().EventTrigger("KeyIsOpen",key);
  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

BasePanel

UI的基础类,我们创建出的所有UI都可以继承自此类,当然也可以只选择为UI的父物体创建,用父物体的脚本来控制子物体的空间

BasePanel并不是管理,而是实现UI功能

public class BasePanel : MonoBehaviour
{
	//使用字典存储UI名和其身上的控件
   public Dictionary<string, List<UIBehaviour>> controlDic
      = new Dictionary<string, List<UIBehaviour>>();
   private void Awake()//在Start之前就得到下列
   {
	  //或的控件并保存在字典中,可根据自己UI搭载的控件更改
      FinChildControl<Button>();
      FinChildControl<Image>();
      FinChildControl<Scrollbar>();
      FinChildControl<Text>();
   }
	//返回名为controlName的UI身上的T控件《若没有则返回null
   protected T GetControl<T>(string controlName) where T : UIBehaviour
   {
      if (controlDic.ContainsKey(controlName))
      {
         for(int i=0;i<controlDic[controlName].Count;i++)
         {	
            if (controlDic[controlName][i] is T)//使用is判断是否为T控件
               return controlDic[controlName][i] as T;
         }
      }

      return null;
   }

	//找到物体及其子物体的UI控件保存至字典中
   private void FinChildControl<T>() where T : UIBehaviour
   {
      T[] controls = this.GetComponentsInChildren<T>();//注意用的是GetComents,返回的是一组
      string objName;//使用名字对控件按物体分类
      for (int i = 0; i < controls.Length; i++)
      {
         objName = controls[i].gameObject.name;
         if(controlDic.ContainsKey(objName))
            controlDic[objName].Add(controls[i]);//注意controlDic中存储的类型为<string, List<UIBehaviour>,所以我们的同一个UI的所有控件都在这个链表中
         else 
            controlDic.Add(objName,new List<UIBehaviour>(){controls[i]});//添加UI到字典中
      }
   }

	//虚函数,可在继承类中自己定义
   public virtual void ShowMe()
   {
      
   }
	//同上
   public virtual void HideMe()
   {
      
   }
   
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

举例,我们创建一个Button,创建此脚本并给与Button,由于继承了BasePanel,Awak函数执行后就获得了Button组件,我们用GetControl得到此UI的Button,并注册事件

public class But : BasePanel
{
    private Button b;//创建Button
    private void Start()
    {
        GetControl<Button>(this.name).onClick.AddListener(Click);
        
    }
    void Click()
    {
        Debug.Log("ButtonClick");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

UIManager

UIManager作为UI管理类,我们能够使用它对UI进行管理,呼出UI、关闭UI,操作UI等,我们将UI层划分为三层,分别为Bot(底层)、Mid(中层)、Top(高层)

//设置枚举,表示层级
public enum E_UI_Layer
{
    Bot,
    Mid,
    Top,
}
//继承自BaseManager,单例模式随时调用
public class UIManager : BaseManager<UIManager>
{	//用字典存储给UI,方便管理
    public Dictionary<string, BasePanel> panelDic
        = new Dictionary<string, BasePanel>();
	
    private Transform bot;
    private Transform mid;
    private Transform top;
	
    //构造函数,用于初始化
    public UIManager()
    {	//利用ResMgr加载画布
        GameObject obj = ResMgr.GetInstance().Load<GameObject>("UI/Canvas");
        Transform canvas = obj.transform;
        GameObject.DontDestroyOnLoad(obj);//UI不随场景切换销毁

        bot = canvas.Find("bot");
        mit = canvas.Find("mid");
        top = canvas.Find("top");
		//UI系统没有EventSystem无法启动
        obj = ResMgr.GetInstance().Load<GameObject>("UI/EventSystem");
        GameObject.DontDestroyOnLoad(obj);
    }
//将此Panel移动到Top层,并且callback委托可传可不传函数
    public void ShowPanel<T>(string panelName,
        E_UI_Layer layer = E_UI_Layer.Top,
        UnityAction<T> callback = null) where T : BasePanel
    {
        //若字典中有注册过此面板
        if (panelDic.ContainsKey(panelName))
        {
            panelDic[panelName].ShowMe();
            if (callback != null)
                callback(panelDic[panelName] as T);
            return;
        }
        //若字典中未注册过此面板,从Resource文件夹中加载
        //使用了lambda表达式
        ResMgr.GetInstance().LoadAsync<GameObject>("UI/"+panelName,(obj)=>
        {
            //把它作为Canvas的子对象
            //并且设置它的相对位置
            //找到父对象
            Transform father = bot;
            switch (layer) {
                case E_UI_Layer.Mit:
                    father = mit;
                    break;
                case E_UI_Layer.Top:
                    father = top;
                    break;
            }
            //设置父对象
            obj.transform.SetParent(father);

            //设置相对位置和大小
            obj.transform.localPosition = Vector3.zero;
            obj.transform.localScale = Vector3.one;

            (obj.transform as RectTransform).offsetMax = Vector2.zero;
            (obj.transform as RectTransform).offsetMin = Vector2.zero;

            //得到预设体身上的脚本(继承自BasePanel)
            T panel = obj.GetComponent<T>();

            //执行外面想要做的事情
            if (callback != null) {
                callback(panel);
            }

            //在字典中添加此面板
            panelDic.Add(panelName, panel);
        });
            
       
    }

    public void HidePanel(string panelName)
    {
        if (panelDic[panelName])
        {
            panelDic[panelName].HideMe();
            //个人感觉没必要
            panelDic[panelName].HideMe();
            GameObject.Destroy(panelDic[panelName].gameObject);
            panelDic.Remove(panelName);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97

MusicMgr

音乐音效管理类,都是些基础,大家应该都能看懂吧

public class MusicMgr : BaseManager<MusicMgr>
{
    private AudioSource bkMusic = null;
    private float bkValue = 1;
    private float soundValue = 1;
    private GameObject soundObj = null;
    private List<AudioSource> soundList = new List<AudioSource>();

    public MusicMgr()
    {
        MonoMgr.GetInstance().AddUpdateListener(update);
    }

    private void update()
    {
        for (int i = soundList.Count - 1; i >= 0; i--)
        {
            if (!soundList[i].isPlaying)
            {
                GameObject.Destroy(soundList[i]);
                soundList.RemoveAt(i);
            }
        }
    }

    public void PlayBKMusic(string musciName)
    {
        if (bkMusic == null)
        {
             GameObject obj = new GameObject("BKMusic");
             bkMusic = obj.AddComponent<AudioSource>();
        }

        ResMgr.GetInstance().LoadAsync<AudioClip>("Music/bk" + musciName, (clip) =>
        {
            bkMusic.clip = clip;
            bkMusic.loop = true;
            bkMusic.volume = bkValue;
            bkMusic.Play();
        });
    }

    public void ChangeBKValue(float v)
    {
        bkValue = v;
        if(bkMusic==null)
            return;
        bkMusic.volume = bkValue;
    }

    public void PauseBKMusic()
    {
        if(bkMusic==null)
            return;
        bkMusic.Pause();
    }

    public void StopBkMusic()
    {
        if(bkMusic==null)
            return;
        bkMusic.Stop();
    }



    public void PlaySound(string musicName, bool isLoop, UnityAction<AudioSource> callback = null)
    {
        if (soundObj == null)
        {
            soundObj = new GameObject();
            soundObj.name = "Sounds";
        }

        AudioSource source = soundObj.AddComponent<AudioSource>();
        ResMgr.GetInstance().LoadAsync<AudioClip>("Music/Sounds/"+musicName, (clip) =>
        {
            source.clip = clip;
            source.loop = isLoop;
            source.volume = soundValue;
            source.Play();
            if (callback != null)
                callback(source);
        });
    }

    public void ChangeSoundValue(float value)
    {
        soundValue = value;
        for (int i = 0; i < soundList.Count; i++)
            soundList[i].volume = value;
    }

    public void StopSound(AudioSource source)
    {
        if (soundList.Contains(source))
        {
            soundList.Remove(source);
            source.Stop();
            GameObject.Destroy(source);
        }
    } 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/761619
推荐阅读
相关标签
  

闽ICP备14008679号