Unity3D如何有效地组织代码?
本文整理自知乎,原文链接:http://www.zhihu.com/question/21070379
问题:
Unity3D可以说是高度的Component-Based Architecture,同时它的库提供了大量的全局变量。
这些都和我曾接触到的cocos2d-x,和非游戏框架有很大出入,
请问各位前辈有没有什么好的方法、模式、框架来组织代码呢?
谢谢!
回答
梁伟国
准确地说,代码作为Unity项目里的一种资源,此问题应该扩展到如何组织Unity资源。简单说说我们的经验:
- Unity有一些自身的约定,譬如项目里的Editor,Plugins等目录作为编辑器,插件目录等等。知名的插件会自己存放一个目录,譬如NGUI等。
所以我们自己的代码,一般目录名会以下划线开头,譬如 "_Scripts", "_Prefabs"等。
对于场景,文档等目录,用两条下划线,以便他们能排在最顶部。
- 代码用C#,别用JS。必要的话用namespace将自己的代码括起来。我们是用namespace把自己积攒的公用库包住。
- C#的注释要认真写,打///就能帮你补全了,没理由偷懒。
- 每个程序文件开头要用一段注释写修改Log,谁改过什么简单留一条说明。就算用了Unity的版本管理或者Git,那些log终究会丢失,只有认真把log写在代码里,才会有意识去认真优化它。
- Unity的脚本逻辑,就功能而言大体分为两种,一种是比较独立的,譬如爆炸之后1秒钟消失,这种单独写个脚本绑定到目标上即可。
更多的是脚本里与其它的脚本进行交互。Unity里提供了一种万金油的方法是SendMessage, 这种方法性能略差,如果你调用的频率不高,随便用也无妨。另一种方法是直接通过对象的实例去调用。
我们的做法是写几个公用的控制器,让它们各司其职,负责各自的事情:
- 写一个一个GlobalManager.cs来控制游戏的全局变量及全局方法。静态类模式。譬如当前玩到第几大关第几小关,玩家的金币数量等。
- 写一个GameController.cs来控制当前关的游戏进程。单实例模式。游戏的主循环也是用它控制。初始化,胜利、失败判定等等。
- 写一个InputController.cs来控制所有的用户输入。单实例模式。鼠标、键盘、触摸屏,我们做游戏是保证同时支持这三种输入的,因为大部分时间是在PC上测试。
关于GameController与InputController的联系,有点让人纠结。一般来讲是在InputContoller里调用GameController.Instance.Foo()执行方法。或者直接对Input写成Listener的模式,让GameController去监听。
- 其它的类似菜单控制器,声音控制器,成就控制器,IAP虚拟道具控制器等等,也是采用类似的方法管理。
- 关于PlayerPref的操作,统一写成静态类的get/set模式,程序中哪里要用则直接读写。
- 如果你的项目里场景的数量少(<5),那么拖入场景的资源可以很随意。如果场景数量很多(几十个,有的解谜游戏每个关卡就是一个场景),那么拖入场景的prefab数量一定要少。
- 设计你的prefab资源里,你要想像当其他人拿到这些资源,是否直接拖入一个空场景里就能run,顶多再简单设置几下。如果你设计的资源不能做到这些,那么得好好重新想想。
写了这些,感觉写不下去了。
想吃透Unity,起码得真做出几款产品放上线才行。真正做产品的过程中会碰到各种各样意想不到的问题,代码不断地被重构和妥协,不存在什么最佳的方案。
暂时就写这些吧,希望能抛砖引玉。
周华
Unity除了挂在Game Object上的代码比较难找,这一点跟其他工具做项目不同外,其他就是每个公司自己的管理风格了。在实际操作中,无非就是文件夹/文件夹/.../文件,名字要起的好。这样就在源代码级别管理好了自己的代码。
至于楼主所提的Component-based architecture,个人在管理过程中会习惯去适应unity的脚本概念,虽然与C++等代码做的项目一样,一样有源代码级的很多manager,但是这些manager的启动不再需要自己做一个类似main一样的入口手动启动,只要挂在某个Game Object上,在Start()中启动就可以。配合Unity的script execution order,慢慢脚本的概念就会扎入你的心里。用Unity,因为逃不开在Game Object上挂脚本,所以,个人觉得还是习惯这种方式,的确在概念上也很简单。唯一要注意的是,一定要对Game Object的名字有一定的约束,养成很好的命名习惯。然后自己再写一些查找工具用来查找用到某个名字的脚本的Game Object,配合起来就会理解Unity这样工具的设计理念:基于脚本的对象化。
举个例子,单机版的一些存储,如果配合Unity的playerprefs和Unity的回调机制(OnApplicationPause(),OnApplicationQuit()),你会发现你不用为save/load去设计存储格式,去设计一个基于虚函数的OnSave()、OnLoad(),更不用需要去考虑各个模块的存储先后问题。Unity都给你做好了。
我不知道有哪些模式,只知道也曾经用C++等熟悉的语言来组织自己的逻辑(因为当初刚开始untiy),但是当我做项目多了,发现其实unity的方式挺简单,也很好用。如果所谓的脚本能做好一件事情,你会发现小即是美。
Unity3D如何有效地组织代码?的更多相关文章
- Unity3D如何有效地组织代码?(转)
问题: Unity3D可以说是高度的Component-Based Architecture,同时它的库提供了大量的全局变量.如何来组织代码呢? 答: - Unity有一些自身的约定,譬如项目里的Ed ...
- DDD:订单管理 之 如何组织代码
背景 系统开发最难的是职责的合理分配,或者叫:“如何合理的组织代码”,今天说一个关于这方面问题的示例,希望大家多批评. 示例背景 参考数据字典 需求 OrderCode必须唯一. Total = Su ...
- Flask实战-留言板-安装虚拟环境、使用包组织代码
Flask实战 留言板 创建项目目录messageboard,从GreyLi的代码中把Pipfile和Pipfile.lock文件拷贝过来,这两个文件中定义了虚拟环境中需要安装的包的信息和位置,进入m ...
- Python基础-修改excel、redis、接口开发、组织代码
pymysql模块补充内容 1. 游标.description():显示表的字段属性 (什么是游标:游标用于交互式应用,就好比word里的光标一样,要修改某个地方,要先把光标移动到这里) 用好这个方法 ...
- 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码?
go语言的开发工具推荐? go语言开发普通程序及开发web程序的时候,应该以哪种目录结构组织代码? 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码? >> golang这个答案 ...
- Unity3D脚本--经常使用代码集
1. 訪问其他物体 1) 使用Find()和FindWithTag()命令 Find和FindWithTag是很耗费时间的命令,要避免在Update()中和每一帧都被调用的函数中使用.在Start() ...
- Go:如何组织代码
备注 此文主要是对官方教程的学习总结,官方教程:http://golang.org/doc/code.html. 工作空间(Workspaces) Go代码必须保持在一个workspace,works ...
- .NET C#基础(6):命名空间 - 组织代码的利器
0. 文章目的 面向C#新学者,介绍命名空间(namespace)的概念以及C#中的命名空间的相关内容 1. 阅读基础 理解C与C#语言的基础语法 2. 名称冲突与命名空间 2.1 一个生活例 ...
- unity3d随机地牢生成代码
现在也是处于失业状态,碰巧看到个面试题是要用unity生成个随机地牢,就把做题过程中的思路和代码记录一下吧. 做完了以后我又想了一下,发现其实根本不需要这么麻烦,果然demo里的代码对我的思路影响还是 ...
随机推荐
- Hibernate 映射
在使用单纯hibernate文件映射时,项目应包含以下文件: hibernate.cfg.xml 放在src/或根目录下 1 <?xml version='1.0' encoding='utf ...
- 云小课 | IPv4枯了,IPv6来了
摘要:本篇主要分享IPv4与IPv6的区别和IPv6的应用场景,助您快速理解华为云IPv6双栈及IPv6 EIP. IPv6的由来 上节课我们讲了公网IP与私网IP,了解了IP地址的一些知识. 我们一 ...
- 【JZOJ4726】种花 题解(贪心+堆)
题目大意:在一个长度为$n$的环型序列中取出$m$个数使这$m$个数的和最大,且要求这$m$个数互不相邻. ---------------------- 考虑维护$nxt$和$lst$,即一个数的前驱 ...
- 系统UISearchController详解
原文链接:https://www.jianshu.com/p/aa9a153a5b58
- MySQL数据库高可用方案
一.什么是高可用性: 高可用性=可靠性,它的本质就是通过技术和工具提高可靠性,尽可能长时间保持数据可用和系统运行,实现高可用性的原则,首先要消除单点故障,其次通过冗余机制实现快速恢复,还有就是实现容错 ...
- Python爬虫开发:反爬虫措施以及爬虫编写注意事项
- 如何利用Python在网上接单,兼职也能月薪过万
- 7、Java 循环结构
本章讲解一下Java中常见的三种循环结构,顺序结构的程序语句只能 被执行一次.使用循环可以解决我们多个常量或者变量的同一类的操作或者更加复杂的操作. 循环 循环结构有三大类: 1.for循环:确定循环 ...
- Bytom Dapp 开发笔记(一):架构设计
简介 研究比原链已经一年了,用比原链做了几个dapp,而且最近还做了一个基于他们插件钱包的dapp,总结了一些遇到的坑,还有一些技术细节,接下来我会分成三章,从dapp设计架构上,到深入到源码分析去帮 ...
- 2020-07-05:tcp和udp的区别和应用场景。如何实现断点续传?
福哥答案2020-07-05: 区别:1.可靠性:tcp可靠.udp不可靠.2.连接性:tcp面向连接.udp无连接.3.报文:tcp字节流.udp面向报文.4.传输效率:tcp低.udp高.5.多点 ...