Unity3D架构小结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tyuiof/article/details/52814511

刚开始学习Unity编程时,感觉非常的不习惯。一直以来,我都是使用基于类的面向对象编程,当转到Unity开发后,发现所有的代码都是拖到一个个组件上面去的,早已习惯了的mvc,mvp等架构思想在Unity上却不太适用了。

所以在我前期开发Unity时,完全是没有架构可言的,每次都是某个组件需要什么功能,我就把相应的功能代码托上去,可是写到后面,我发现整个项目的逻辑越来越混乱,各种组件在代码中互相引用,修改某一个组件上的代码就会导致其他组件的修改。后来当我慢慢了熟悉Unity的开发,熟悉了这种基于组件的编程思想后,开始慢慢的组织自己的代码逻辑和项目架构。所以在这里,我将我这段时间对于U3D项目架构的总结记录下来。

一 文件目录架构

Unity官方文档介绍的文件目录架构如下

  • Assets:主文件夹,包含所有工程需要用到的资源。

    • Editor:所有在Editor和它的子文件夹的脚本,都不会作为运行期脚本被编译,而是作为动态添加Unity编译器功能的脚本来编译。在该文件夹和其子文件夹的脚本不能被添加到GameObject上。

    • Editor Default Resources:必须作为Assets的子文件夹,作为Editor脚本的资源使用,通过函数EditorGUIUtility.Load来使用。

    • Gizmos:场景面板中的图标图片资源,使用Gizmos.DrawIcon 函数在场景面板新建图标,图标的图片资源必须位于这个文件夹内。(比如Unity的各种插件)

    • Plugins:所有的插件资源,包括用C/C++编写的Dll库。

    • Resources:一般用来存放需要通过代码初始化使用的资源,可以放在工程中的任意文件夹中,在Resources文件夹中的文件可以通过Resources.Load 来读取。方式如下。

      rend.material.mainTexture = Resources.Load(“glass”) as Texture;
      GameObject instance = Instantiate(Resources.Load(“enemy”,typeof(GameObject))) as GameObject;

    • Standard Assets:导入标准材质包时新建的,拥有自己的编译顺序。

    • StreamingAssets:通过Application.streamingAssetsPath 获取目录路径,该目录中的文件将会原封不动的被拷贝到不同的平台上,每个平台对应的目录不一致,但是都可以通过上述方法获得。一般用来存放视频等资源文件。

    • Hidden Assets:一般用来存放README以及一些操作系统生成的临时文件,这些文件/文件夹一般以. ~ 或者名为cvs 或者扩展名是tmp 。

二 代码组织架构

①小型项目
开发小型项目时,不需要太复杂的架构方式,直接将逻辑脚本拖到响应的控件即可,但是这个时候有一个点需要考虑的就是脚本内的代码会随着逻辑的增加而越来越多,所以,这个时候最好的做法是将脚本拆分成几个脚本,每个脚本处理相应的逻辑业务,然后全部添加到组件上去。

我们以做一个飞机大战的小游戏举例,飞机有前后左右飞行的逻辑,有发射子弹的逻辑,有被击中的逻辑……我们可以把这些逻辑分别写在不同的脚本上,然后挂载到飞机上,而不是将所有的逻辑放在一个脚本内。这样我们对飞机的各个逻辑业务会更加的清晰,也更好控制。

②中小型项目
当项目越来越大时,通过拆分代码逻辑的方法已经不够用了,所以这个时候需要用统一的Manager来管理业务逻辑。在一个中型项目中,一般需要需要Level Manager,Pool Manager和Save Manager这三个管理类。下面我来说说这三个Manager的作用

  • Level Manager
    当游戏的关卡比较多时,利用Application.LoadLevel()方法加载关卡已经比较繁琐了,这个时候需要一个Level Manager来专门管理需要加载的关卡,并可以在里面配置加载策略,方便的更改加载关卡的顺序,方式等。
      
  • Pool Manager
    游戏中经常出现来频繁创建,销毁的物体,比如怪物,子弹等,如果频繁GameObject.Instantiate()来创建,用Deatory()方法来销毁会占用大量内存,引起GC,这个时候就需要一个Pool Manager来统一生成,缓存,或者销毁这些对象。
    我们来看看PoolManager的用法
  Private List<GameObject > dormantObjects =new List<GameObject>()
  public GameObject Spawn(GameObject go)  
  {
  //如果dormantObjects中存在这个object则直接取出来,否则创建该GameObject
  }
  // 将用完的GameObject缓存dormantObjects中
  public void Despawn(GameObject go)  
  {
       go.transform.parent = PoolManager.transform;
       go.SetActive(false);
       dormantObject.Add(go);
       Trim();
  }
  //最久不使用的先销毁
  public void Trim()  
  {
       while (dormantObjects.Count > Capacity)
       {
            GameObject dob = dormantObjects[0];
            dormantObjects.RemoveAt(0);
            Destroy(dob);
       }
  }

我们可以看到,PoolManager的作用就是将我们需要频繁创建和销毁的预制体放在一个list中,当容器满了之后,删除最底层使用频度最少的预制体。dormantObjects可以有很多个,用来分别存放不同的物体。

这里写图片描述

  • Save Manager
    Save Manager可以专门用来存储和加载游戏,通过将数据序列化(Serialize)以二进制的形式保存下来,会让游戏加载的更快。

③大型项目
在大型的项目中,上面三个Manager已经不够用,这个时候我们需要更多的Manager来进行统一管理。

这里写图片描述


可以看到,一个项目中有一个MainManager来统一管理不同的子Manager。子Manager中又有EventManager对事件进行管理,AduioManager对音效进行管理等等。

 

在比较大的项目中,虽然设置了很多Manager来进行统一管理,但是项目的结构还是会越来越混乱。所以这个时候我们可以采用MVCS的模式。这种设计思想我是从StrangeIOC这款Unity插件中学来的。MVCS就是在MVC的基础上加了一层Service。我们来看看这种设计思想。

这里写图片描述

 

这种的设计模式的业务流程是这样的

  1. 玩家点击了一下UI
  2. VIEW中的mediator得到通知(回调),因为它绑定了UI事件
  3. mediator触发了一次CONTROLLER中command执行指令,因为mediator和command进行了绑定
  4. command执行自己的execute方法
  5. 请求Service从一个文件中读取数据

当然,MVCS的设计模式只是我们设计架构时参考的一种思路。大型Unity项目开发的经验我也不是很足,等以后有了更多的经验之后,我会继续补充Unity的架构知识。

原文地址:https://blog.csdn.net/LJH_Gemini/article/details/89738091

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

相关推荐


这篇文章将为大家详细讲解有关Unity3D中如何通过Animator动画状态机获取任意animation clip的准确播放持续时长,小编觉得挺实用的,因此分享给大家做个参考,
这篇文章主要介绍了Unity3D如何播放游戏视频,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解
这篇文章给大家分享的是有关Unity3D各平台路径是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1、Resources路径 Reso...
小编给大家分享一下Unity3D如何实现移动平台上的角色阴影,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!由于目前主流使用Unity3.x在移动平...
如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希
这篇文章主要介绍Unity3D如何实现动态分辨率降低渲染开销,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!之前项目降低分辨率我们都普...
这篇文章主要介绍了unity3d中如何使用屏幕空间改善shadowmap漏光,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编...
这篇文章主要介绍unity3d如何实现基于屏幕空间的描边,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Outline(Based on Image Space)由...
这篇文章给大家分享的是有关unity3d中导入fbx时的Scale是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在Unity中点击GameOb...
这篇文章主要为大家展示了“unity3d中如何实现ttc转ttf及制作字体”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习
这篇文章主要介绍了unity3d中水彩风渲染有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了...
这篇文章将为大家详细讲解有关unity3d中图像压缩原理是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1 图像可压缩...
这篇文章给大家分享的是有关unity3d中光照公式有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。漫反射、高光、物理渲染(PBR...
小编给大家分享一下unity3d中光照探针的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我...
这篇文章将为大家详细讲解有关Unity3D中Rendering Paths及LightMode的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有
这篇文章将为大家详细讲解有关unity3d中图形学的光照原理是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。首先,在...
这篇文章给大家分享的是有关unity3d中图片渲染流程是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。相关名词GPU(Graphic Pr...
本篇我们来介绍一下左侧工具栏中基本绘制的应用。 一、墙体绘制直墙 & 矩形墙绘制墙体时,可以看到上方的工具栏中对墙体进行参数的设定。 弧形墙在建筑版的户...
xlua是由腾讯维护的一个开源项目,我们可以在github上下载这个开源项目并查看一些相关文档官网:https://github.com/Tencent/xLua配置文档:https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/hotfix.md常见问题解答:https://github.com/Tencent/xLua/blob/master/Assets/
我们都知道,一个三维场景的画面的好坏,百分之四十取决于模型,百分之六十取决于贴图,可见贴图在画面中所占的重要性。在这里我将列举一些贴图,并且初步阐述其概念,理解原理的基础上制作贴图,也就顺手多了。我在这里主要列举几种UNITY3D中常用的贴图,与大家分享,希望对大家有帮助。01 首先