1、特殊文件夹
Unity工程根目录下,有三个特殊文件夹:Assets、Library、ProjectSettings
Assets
Unity工程中所用到的所有Asset都放在该文件夹中,是资源文件的根目录,很多API都是基于这个文件目录的,查找目录都需要带上Assets,比如AssetDatabase。
Library
Unity会把Asset下支持的资源导入成自身识别的格式,以及编译代码成为DLL文件,都放在Library文件夹中。
ProjectSettings
编辑器中设置的各种参数
下面都是存在Assets目录下的文件的了。
Editor
为Unity编辑器扩展程序的目录,可以在根目录下,也可以在子目录下,只要名字叫“Editor”,而且数量不限。Editor下面放的所有资源文件和脚本文件都不会被打进包中,而且脚本只能在编辑器模式下使用。一般会把扩展的编辑器放在这里,或只是编辑器程序用到的dll库,比如任务编辑器、角色编辑器、技能编辑器、战斗编辑器……以及各种小工具。
Editor Default Resources
名字带空格,必须在Assets目录下,里面放编辑器程序用到的一些资源,比如图片,文本文件等。不会被打进包内,可以直接通过EditorGUIUtility.Load去读取该文件夹下的资源。
Gizmos
Gizmos.DrawIcon在场景中某个位置绘制一张图片,该图片必须是在Gizmos文件夹下。
void OnDrawGizmos() {
Gizmos.DrawIcon(transform.position, “0.png”, true);
}
OnDrawGizmos是MonoBehaviour的生命周期函数,但是只在编辑器模式下每一帧都会执行。Gizmos类能完成多种在场景视图中绘制需求,做编辑器或调试的时候经常会用到,比如在场景视图中绘制一条辅助线。(用Debug.DrawLine,Debug.DrawRay也可以绘制简单的东西)
Plugins
该文件夹一般会放置几种文件,第三方包、工具代码、sdk。
plugin分为两种:Managed plugins and Native plugins
Managed plugins:就是.NET编写的工具,运行于.NET平台(包括mono)的代码库,可以是脚本文件,也可以本身是DLL。NGUI源码就放在该文件夹下面的。
Native plugins:原生代码编写的库,比如第三方sdk,一般是dll、so、jar等等。
该文件夹下的东西会在standard compiler时编译(最先编译),以保证在其它地方使用时能找到。
Resources
存放资源的特殊文件夹,可以在根目录下,也可以在子目录下,只要名字叫“Resources”就行,比如目录:/xxx/xxx/Resources 和 /Resources 是一样的,而且可有多个叫Resources的文件夹。Resources文件夹下的资源不管用还是不用都会被打包进.apk或者.ipa,因为Unity无法判断脚本有没有访问了其中的资源。需要注意的是项目中可以有多个Resources文件夹,所以如果不同目录的Resources存在同名资源,在打包的时候就会报错。
Resources中全部资源会被打包成一个缺省的AssetBundle(resources.assets)。
在该文件夹下的资源,可以通过Resources类进行加载使用。API地址
Standard Assets
存放导入的第三方资源包。
StreamingAssets
该文件夹也会在打包的时候全部打进包中,但它是“原封不动”的打包进去(直接拷贝到的包里)。游戏运行时只能读不能写。
不同的平台最后的路径也不同,可以使用unity提供的Application.streamingAssetsPath,它会根据平台返回正确的路径,如下:
Mac OS or Windows:path = Application.dataPath + “/StreamingAssets”;
IOS:path = Application.dataPath + “/Raw”;
Android:path = “jar:file://” + Application.dataPath + “!/assets/”;
我们一般会把初始的AssetBundle资源放在该文件夹下,并且通过WWW或AssetBundle.LoadFromFile加载使用。
Hide Assets
隐藏文件夹和文件
以".“开头
以”~“结尾
名字为"cvs”
扩展名为".tmp"
一些通常的Asset类型
Image: 支持绝大多数的image type,例如BMP、JPG、TIF、TGA、PSD
Model:eg、.max、.blend、.mb、.ma,它们将通过FBX插件导入。或者直接在3D app导出FBX放到unity project中
Mesh and Animations:unity支持绝大多数流行的3D app的model(Maya、Cinema 4D、3ds Max、Cheetah3D、Modo、Lightwave、Blender、SketchUp)
Audio Files:如果是非压缩的audio,unity将会根据import setting压缩导入(更多)
Other:
Asset Store
里面有很多免费和收费的插件,可以供开发者下载使用。
下载的第三方工具是以package文件存在,导入package:
package.png
导入
unity会自动导入Asset目录下的资源,可以是unity支持的,也可以是不支持的,而在程序中用到的(比如二进制文件)。
当在Asset下进行保存、移动、删除等修改文件的操作,unity都会自动导入。
自定义导入
导入外界的unity可识别的Asset时,可以自定义导入设置,在工程中点击资源文件,然后Inspector视图中就会看到相应的设置:
导入结果
导入资源之后,除了要生成.meta文件,unity并不是直接使用这些资源的,而是在导入的过程中,生成了unity内部特定的格式(unity可识别)文件在游戏中使用,储存在Library目录下,而原始资源不变,仍然放在原来位置。当然,每次修改原始文件,unity都会重新导入一次,才能在unity中看到改过之后的样子。
正因为Library存放了导入资源的结果,所以每次删除Library或里面某个文件,都会让unity重新导入相应的资源(生成内部格式),但对工程没有影响。
.meta文件
Asset中的所有文件、文件夹,经过unity的导入过程后,会为每个都生成一个.meta文件,这个文件是unity内部管理文件的重要内容,里面记录着一些信息。
你知道unity是怎么管理资源依赖关系的吗?可以试着更改一个挂在prefab上的脚本的目录或者名字,而这些prefab依然可以正常的调用那些脚本。
unity在第一次导入新文件的时候,会生成一个Unique ID,用来标志这个asset,它就是unity内部用来区分asset的。Unique ID是全局唯一的,保存在.meta文件中。
在unity中资源间的依赖关系引用都是用Unique ID来实现的,如果一个资源丢失了.meta文件,那依赖它的资源就找不到它了。
.meta文件内容如下,包括Unique ID和Import Setting的内容
meta.png
脚本
unity支持三种脚本语言,分别是C#、JavaScript、Boo,最常用的是前两种,当然还有后来扩展的支持Lua脚本的库(slua、ulua)。
生成的对应的工程.png
1.编译顺序
编译顺序的原则是在第一个引用之前编译它,参考官网文档可以知道,Unity中的可以将脚本代码放在Assets文件夹下任何位置,但是不同的位置会有不同的编译顺序。规则如下:
(1) 首先编译Standard Assets,Pro Standard Assets,Plugins文件夹(除Editor,可以是一级子目录或是更深的目录)下的脚本;
(2) 接着编译Standard Assets,Pro Standard Assets,Plugins文件夹下(可以是一级子目录或是更深的目录)的Editor目录下的脚本;
(3) 然后编译Assets文件夹下,不在Editor目录的所有脚本;
(4) 最后编译Editor下的脚本(不在Standard Assets,Pro Standard Assets,Plugins文件夹下的);
基于以上编译顺序,一般来说,我们直接在Assets下建立一个Scripts文件夹放置脚本文件,它处于编译的“第三位”。
2.编译结果:
项目工程文件夹中会生成类似如下几个文件, 按顺序分别对应着上述四个编译顺序:(GameTool是项目名称)
GameTool.CSharp.Plugins.csproj
GameTool.CSharp.Editor.Plugins.csproj
GameTool.CSharp.csproj
GameTool.CSharp.Editor.csproj
所有脚本被编译成几个DLL文件,位于工程根目录 / Library / ScriptAssemblies。
生成如下三个dll:
Assembly-CSharp-Editor.dll:包含所有Editor下的脚本
Assembly-CSharp-firstpass.dll:包含Standard Assets、Pro Standard Assets、Plugins文件夹下的脚本
Assembly-CSharp.dll:包含除以上两种,在Assets目录下的脚本。
Plugins(doc)
内容包括了Plugin导入设置、怎样创建使用两种Plugin、怎样利用底层渲染接口以及一些基础知识。
在打包的时候,会把plugin里面的各种库,拷贝到包体中相应的位置(不同平台不一样,具体在可以把工程分别打成几个平台的包)
win平台
这是win32平台的包,Managed里面放置的托管库,Mono里面放的是mono的库,Plugins是平台库(native plugin)
分平台打包,就需要对不同平台的plugin区分,方法是在Plugins目录下建立相应平台的文件夹,unity在为不同平台打包的时候,除了会将相应平台的plugin里的脚本编译成Assembly-CSharp-firstpass.dll,还会把已经是dll、so等库直接拷贝到包内相应位置。
Plugins/x86:win32位平台plugin
Plugins/x86_64:win64位平台plugin
Plugins/Android:Android平台
Plugins/iOS:iOS平台
Object
UnityEngine.Object是所有类的基类,它描述了Asset上使用的所有resource的序列化数据,它有几个重要的派生类:GameObject,Component,MonoBehaviour
GameObject
GameObject是组件的容器,所有Component都在可以挂在上面,Unity以组价化思想构建,所有功能拆分成各个组件,需要某个功能只需挂上相应的组件,组件之间相互独立,逻辑互补交叉。当然组件式开发也有最大的弊端就是组件之间的交互。
Component
Component作为组件的基类,unity中有大量的组件,Transform、Renderer、Collider、MeshFilter都是组件。
MonoBehaviour
开发时创建的脚本,需要挂在GameObject上的脚本都是继承自MonoBehaviour。
ScriptableObject
自定义可被Unity识别的资源类型,可打成AssetBundle,可通过Resources or AssetBundle加载。
序列化
Asset和Object的关系
Object作为Asset的序列化数据,比如以Texture导入一张图片,那么就用Texture对象记录描述了该图片。
Asset可能有多个Object,比如prefab的GameObject上挂着多个组件,这样Asset和Object就是一对多的关系。那么问题来了,同一个Object怎么区分分别挂在不同GameObject上的对象的?等等,这里是一定要区分的,因为它们要包含序列化数据(在Inspector视图设置的),而不是在游戏运行中再new。
Class ID 和 File ID(object id)
先梳理一下关系,unity通过guid找到asset,其中asset上可能又挂了很多组件,每个组件又对应着一个class,而在序列化的时候是对象。Class ID是unity定义好的(传送),File ID是为对象生成的id,也就是说,我用guid + (class id 可有) + file id 就能确定某个资源上的组件对象。
YMAL
是一种标记语言,如果不了解语言格式可以看网站。
Text-Based Scene Files
和二进制文件一样,unity还提供了基于文本的场景文件,使用YAML标记语言,通过文本描述了asset和object组件之间的关系是怎么关联、保存数据等。
通过设置Edit -> Project Setting -> Editor -> Asset Serialization -> Force Text,我们可以查看所有Object信息了。