博客
关于我
Unity程序基础框架学习
阅读量:446 次
发布时间:2019-03-06

本文共 9711 字,大约阅读时间需要 32 分钟。

Unity 资源管理与模块化开发实践指南

在Unity开发过程中,资源的管理与模块化架构的搭建是保证项目高效开发、维护和优化的关键环节。本文将详细介绍常见的资源管理方式以及多个核心模块的实现方法,帮助开发者构建高效、灵活的游戏开发框架。

一、资源管理方式

在Unity项目中,所有资源(如脚本、模型、贴图等)都需要在Assets目录下管理。为了确保资源的组织和维护,通常会按照功能模块划分文件夹。常见的文件夹划分方式包括:

  • Scripts:存放所有脚本文件。
  • Scenes:存放场景文件。
  • Resources:存放在脚本中使用的资源文件。
  • Prefabs:存放预制体文件。
  • 这种分类方式不仅有助于资源的快速定位,还能通过模块化管理降低代码冗余和维护难度。


    二、单例模式基类实现

    在游戏开发中,某些组件(如UI面板、游戏管理类)往往只能有一个实例存在。单例模式是一种常用的设计模式,确保类的实例在程序生命周期内只存在一个。以下是实现单例模式的两种常见方式:

  • 单例模式基类
  • public class BaseManager
    where T : MonoBehaviour{ private static T instance; public static T Instance { get { if (instance == null) instance = new T(); return instance; } }}
    1. 继承MonoBehaviour的单例模式
    2. public class SingleMono
      : MonoBehaviour where T : MonoBehaviour{ private static T instance; public static T Instance { get { return instance; } } protected virtual void Awake() { instance = this as T; }}
      1. 自动挂载单例模式
      2. public class SingleAutoMono
        : MonoBehaviour where T : MonoBehaviour{ private static T instance; public static T Instance { get { if (instance == null) { GameObject obj = new GameObject(); obj.name = typeof(T).ToString(); instance = obj.AddComponent
        (); } return instance; } } protected virtual void Awake() { instance = this as T; }}

        这些实现方式允许开发者在需要单例管理的组件中继承基类或脚本,只需在需要使用的场景中挂载即可实现单例功能。


        三、缓存池模块基础

        为了优化游戏性能,缓存池是一种常用的资源管理方式。缓存池的主要思想是重复使用已经加载的物体,而不是每次都新建物体。以下是一个简单的缓存池实现示例:

        public class PoolData{    public GameObject rootObj;    public List
        poolList; public PoolData(GameObject obj, GameObject poolObj) { rootObj = new GameObject(obj.name); rootObj.transform.parent = poolObj.transform; poolList = new List
        (); } public void PushObj(GameObject obj) { poolList.Add(obj); obj.transform.parent = rootObj.transform; obj.SetActive(false); } public GameObject GetObject() { GameObject obj = poolList[0]; poolList.RemoveAt(0); obj.SetActive(true); return obj; }}public class PoolMgr : BaseManager
        { public Dictionary
        poolDic = new Dictionary
        (); public GameObject poolRoot; public GameObject GetObject(string name) { GameObject obj = null; if (poolDic.ContainsKey(name) && poolDic[name].poolList.Count > 0) { obj = poolDic[name].GetObject(); } else { obj = Instantiate(Resources.Load
        (name)); obj.transform.parent = null; } return obj; } public void PushObj(string name, GameObject obj) { if (poolRoot == null) poolRoot = new GameObject("Pool"); if (!poolDic.ContainsKey(name)) poolDic.Add(name, new PoolData(obj, poolRoot)); poolDic[name].PushObj(obj); } public void Clear() { poolDic.Clear(); poolDic = null; }}

        通过缓存池技术,可以显著减少内存消耗和垃圾回收的频率,提升游戏性能。


        四、事件中心模块

        事件中心是一种解耦合的事件处理方式,适用于在多个脚本之间传递事件。通过事件中心,游戏中的各个组件可以通过注册和分发委托来实现松耦合的通信。以下是一个简单的事件中心实现:

        public class EventCenter : BaseManager
        { private Dictionary
        > eventDic = new Dictionary
        >(); public void AddEventListener(string name, UnityAction
        action) { if (eventDic.ContainsKey(name)) eventDic[name] += action; else eventDic.Add(name, action); } public void RemoveEventListener(string name, UnityAction action) { if (eventDic.ContainsKey(name)) eventDic[name] -= action; } public void Clear() { eventDic.Clear(); eventDic = null; } public void EventTrigger(string name, object param) { if (eventDic.ContainsKey(name)) eventDic[name](param); }}

        通过事件中心,开发者可以在不直接引用目标组件的情况下,轻松地分发和响应各种事件,实现高效的代码维护。


        五、公共Mono模块

        为了减少对MonoBehaviour的依赖,公共Mono模块提供了一种灵活的脚本执行方式。通过将更新函数和生命周期管理封装到公共模块,开发者可以在不继承MonoBehaviour的情况下,实现类似的功能。

        public class MonoController : MonoBehaviour{    private event UnityAction updateEvent;        private void Start()    {        DontDestroyOnLoad(gameObject);    }        private void Update()    {        if (updateEvent != null)            updateEvent();    }        public void AddUpdateListener(UnityAction fun)    {        updateEvent += fun;    }        public void RemoveUpdateListener(UnityAction fun)    {        updateEvent -= fun;    }}
        public class MonoMgr : BaseManager
        { private MonoController controller; public MonoMgr() { GameObject obj = new GameObject("MonoController"); controller = obj.AddComponent
        (); } public void AddUpdateListener(UnityAction fun) { controller.AddUpdateListener(fun); } public void RemoveUpdateListener(UnityAction fun) { controller.RemoveUpdateListener(fun); }}

        通过公共Mono模块,开发者可以在不直接依赖MonoBehaviour的情况下,实现高效的脚本生命周期管理。


        六、场景切换模块

        场景切换通常伴随着资源加载过程,为了优化性能和用户体验,场景切换应尽可能使用异步加载。以下是一个简单的场景切换实现:

        public class SceneMgr : BaseManager
        { public void LoadScene(string name, UnityAction fun) { SceneManager.LoadScene(name); fun(); } public void LoadSceneAsyn(string name, UnityAction fun) { StartCoroutine(ReallyLoadSceneAsyn(name, fun)); } private IEnumerator ReallyLoadSceneAsyn(string name, UnityAction fun) { AsyncOperation ao = SceneManager.LoadSceneAsync(name); while (!ao.isDone) { EventCenter.Instance.EventTrigger("Loading", ao.progress); yield return ao.progress; } fun(); }}

        通过异步加载场景,开发者可以在场景切换过程中执行其他任务,如进度条更新或UI交互。


        七、资源加载模块

        资源管理是游戏开发中的核心任务之一。资源加载框架可以帮助开发者高效地管理资源加载过程,包括同步和异步加载。

        public class ResMgr : BaseManager
        { public T Load
        (string name) where T : Object { T res = Resources.Load
        (name); if (res is GameObject) return Instantiate(res); return res; } public void LoadAsync
        (string name, UnityAction
        callback) where T : Object { StartCoroutine(ReallyLoadAsync(name, callback)); } private IEnumerator ReallyLoadAsync
        (string name, UnityAction
        callback) { ResourceRequest rr = Resources.LoadAsync
        (name); yield return rr; if (rr.asset is GameObject) callback(GameObject.Instantiate(rr.asset) as T); else callback(rr.asset as T); }}

        通过资源加载框架,开发者可以根据需求选择同步或异步加载资源,并在加载过程中执行自定义操作。


        八、输入管理模块

        输入管理模块的主要目标是将输入事件与业务逻辑分离,减少耦合度。通过事件中心和公共Mono模块,开发者可以轻松实现输入事件的监听和响应。

        public class InputMgr : BaseManager
        { private bool isOpenInput = false; public InputMgr() { MonoMgr.Instance.AddUpdateListener(Update); } private void Update() { if (!isOpenInput) return; foreach (KeyCode key in Enum.GetValues(typeof(KeyCode))) CheckKeyCode(key); } private void CheckKeyCode(KeyCode key) { if (Input.GetKeyDown(key)) { EventCenter.Instance.EventTrigger("Key " + key.ToString() + " Down", key); } if (Input.GetKeyUp(key)) { EventCenter.Instance.EventTrigger("Key " + key.ToString() + " Up", key); } }}

        通过输入管理模块,开发者可以集中处理所有输入事件,并通过事件中心将输入事件分发给相关组件。


        九、UI管理模块

        UI管理模块的目标是统一管理所有UI面板,实现松耦合的UI交互。以下是一个简单的UI管理实现:

        public class UIManager : BaseManager
        { public Dictionary
        panelDic = new Dictionary
        (); private Transform canvas; private Transform bot; private Transform mid; private Transform top; private Transform system; public UIManager() { GameObject canvasObj = ResMgr.Instance.Load
        ("UI/Canvas"); GameObject.DontDestroyOnLoad(canvasObj); canvas = canvasObj.transform; bot = canvas.Find("Bot"); mid = canvas.Find("mid"); top = canvas.Find("Top"); system = canvas.Find("System"); GameObject eventSystemObj = ResMgr.Instance.Load
        ("UI/EventSystem"); GameObject.DontDestroyOnLoad(eventSystemObj); } public void ShowPanel
        (string panelName, E_UI_Layer layer, UnityAction
        callBack = null) { if (panelDic.ContainsKey(panelName)) { BasePanel panel = panelDic[panelName]; if (panel is T) { panel.gameObject.SetActive(true); if (callBack != null) callBack(panel as T); } } else { ResMgr.Instance.LoadAsync
        ("UI/" + panelName, (obj) => { Transform father = bot; switch (layer) { case E_UI_Layer.system: father = system; break; case E_UI_Layer.mid: father = mid; 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; T panel = obj.GetComponent
        (); if (callBack != null) callBack(panel); panelDic.Add(panelName, panel); }); } } public void HidePanel(string panelName) { if (panelDic.ContainsKey(panelName)) { panelDic[panelName].gameObject.SetActive(false); } } public T GetPanel
        (string name) where T : BasePanel { if (panelDic.ContainsKey(name)) { BasePanel panel = panelDic[name]; if (panel is T) return panelDic[name] as T; } return null; }}

        通过UI管理模块,开发者可以轻松地展示和隐藏各个UI面板,并通过事件中心实现松耦合的UI交互。


        总结

        通过以上多个模块的实现,开发者可以构建一个高效、灵活的游戏开发框架。从资源管理到模块化开发,再到事件中心和输入管理,每个模块都为游戏开发提供了强大的支持。这些技术和实现方法不仅可以提升开发效率,还能显著优化游戏性能,使游戏运行更加流畅和稳定。

    转载地址:http://xohyz.baihongyu.com/

    你可能感兴趣的文章
    NYOJ 737:石子合并(一)(区间dp)
    查看>>
    nyoj 91 阶乘之和(贪心)
    查看>>
    nyoj------203三国志
    查看>>
    NYOJ-525 一道水题
    查看>>
    NYOJ127星际之门(一)
    查看>>
    nyoj58 最少步数
    查看>>
    N皇后问题
    查看>>
    N皇后问题
    查看>>
    n种方式教你用python读写excel等数据文件
    查看>>
    OAuth 2.0 MAC Tokens
    查看>>
    OAuth 及 移动端鉴权调研
    查看>>
    OAuth2 + Gateway统一认证一步步实现(公司项目能直接使用),密码模式&授权码模式
    查看>>
    OAuth2 Provider 项目常见问题解决方案
    查看>>
    OAuth2 vs JWT,到底怎么选?
    查看>>
    Vue.js 学习总结(14)—— Vue3 为什么推荐使用 ref 而不是 reactive
    查看>>
    oauth2-shiro 添加 redis 实现版本
    查看>>
    OAuth2.0_JWT令牌-生成令牌和校验令牌_Spring Security OAuth2.0认证授权---springcloud工作笔记148
    查看>>
    OAuth2.0_JWT令牌介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记147
    查看>>
    OAuth2.0_介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记137
    查看>>
    OAuth2.0_完善环境配置_把资源微服务客户端信息_授权码存入到数据库_Spring Security OAuth2.0认证授权---springcloud工作笔记149
    查看>>