Unity工程目录结构

 

一般一个纯粹的Unity工程的目录结构由三个目录组成。

  • Assets: 工程中的所有脚本和资源存放位置,此目录需要通过svn(或git等)进行管理;
  • ProjectSettings: 工程设置目录,例如哪些场景需要编译等,需要通过svn进行管理;
  • Library:工程编译的中间文件,包括 Atlas, Shader, metadata等,Unity运行需要,不存在会自动生成,不需要通过svn进行管理。

Asset目录内容

Asset中的内容分为两部分:

  • 脚本:脚本如果使用C#进行代码编写一般会生成四个工程;
  • 资源:资源可以分为三类,Resoueces目录的资源,StreamingAssets目录的资源和其他资源。

脚本以及编译顺序

脚本内容:

  • Assembly-CSharp-first-pass.csproj:包括了 Assets 目录下 Standard Assets, Standard Assets Pro, Plugins 三个目录里面的脚本;
  • Assembly-CSharp-Editor first-pass.csproj:包括了上述三个目录下 Editor 子目录里面的脚本;
  • Assembly-CSharp.csproj:包括了除了上述三个目录和所有 Editor目录下的其他脚本;
  • Assembly-CSharp-Editor.csproj:包括了其他 Editor 目录下的所有脚本。

划分成多个工程理由:

  • editor 和 runtime 分开,工具和游戏分开;
  • 减少编辑的时候的编译时间,一般只会对一个工程进行修改,此时主要编译其中一个工程即可。

注意:

  • 上述四个工程的依赖关系是,后编译的资源可以依赖于前面的工程,而不能相反;
  • editor 在 runtime 之后,保证 editor 工具可以访问 runtime 脚本。

脚本编译流水线

 

  • Android 平台运行时使用 mono 虚拟机,运行C#程序集,使用 JIT 编译方式;
  • iOS 平台使用 AOT 编译方式,最后编译成的是native 可运行代码。

资源类型

简要列举一下,具体每种类型的资源学问较多,需要单独学习。

  • 场景(.scene)
  • 预设(.prefab)
  • 模型(.fbx. .3dmax …)
  • 网格(.mesh)
  • 动画片段(.anim)
  • 材质(.material)
  • Shader(.shader)
  • 图片精灵
  • 纹理(Texture)
  • 字体(Font)

资源分类

 

按照我的个人理解,资源就分为这两种类型:

  • 纯资源一般是艺术家(美术)的工作结晶,直接导入 Unity 即可,Unity 通过 XXXImporter 来获取想要的数据,如Mesh, Animation, Texture等。
  • 解释资源则是Unity为了在纯资源的基础上封装得到的资源,如Scene, Prefab等。

资源编译内容

 

上述三部分资源最终会被打包到工程中:

  • Assets/xxx/Resources 目录中的内容, Unity会自动将资源的依赖和依赖关系打到安装包中;
  • Assets/StreamingAssets 会原封不动的拷贝到安装包中;
  • ProjectSettings中相关的Scenes以及GraphicSettings中的Shaders。

场景加载方法

 

这个前面有讲过,这里就不细述了。3D游戏一般都采用上述方式进行场景加载。

Resources目录资源动态加载和卸载

 

  • Resources.Load 可以加载 Resources 目录中的一个资源,参数以 Resources 目录为根目录,且不需要后缀名,然后Unity也提供了异步加载资源的方法;
  • Resources.UnloadAsset可以卸载上述 API 加载的资源,对 GameObject 不起作用;
  • Resources.UnloadUnusedAssets 可以通过 GC 方式对所有未引用的资源进行卸载;
  • Editor环境提供了 AssetDataBase.LoadAssetAtPath,一般在写 Editor 工具时候会用到。

StreamingAssets目录资源记载

  • iOS: 使用 File.Read 方法直接从 Application.streamingAssetPath 进行读取;
  • Android:
  • 使用 WWW 进行读取,内容在 WWW.bytes 当中;
  • 使用其他支持从jar包中读取资源的API进行读取;
  • 使用WWW拷贝到document目录,然后使用 File.Read 等文件方法读取。

资源档案meta文件

每个 Assets 目录中的资源都会生成有一个meta文件“伴读”,该文件的作用有二:

  • Import 资源保存 ImportSetting;
  • 保存每个资源的 guid,后文介绍。
    注意该文件需要纳入SVN进行管理,否则会导致资源引用关系在不用项目成员之间发生混乱。

资源”身份证”——guid

 

Assets每个资源都有一个meta文件,文件中记录了一个 guid,这个guid用于记录资源之间的引用关系,引用关系在介绍到后文的 fileID 后一并介绍。
这里介绍 guid 的生成规则:

  • 工程新import或者创建一个资源,生成 meta 文件和 guid;
  • 删除meta文件后,重新导入资源会生成新的 meta 文件和 guid;
  • 在 非Unity中移动资源位置,会重新生成新的 meta 文件和 guid。
    另外guid的生成规则不是单纯按照目录结构或者资源内容来的,多次生成的guid是不同的,这也就是meta文件需要提交的原因,防止同一个资源在不同人的工程中生成不同的guid。

fileID和资源引用关系

首先介绍 fileID,fileID用于标识资源内部的资源。一般fileID也是直接记录在 meta 文件里面的。

  • 资源间的依赖关系使用<guid, fileID>来确定;
  • 资源内部的依赖关系使用 fileID。

例如我在 Unity 中创建了如下的 cube prefab,上面引用了一张贴图,贴图文件 guid 是 ec74a48d86d393d4ea70da2afd20af67,最后的prefab文件如下所示。

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &154222
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 4
  m_Component:
  - 4: {fileID: 454222}
  - 23: {fileID: 2354222}
  m_Layer: 0
  m_Name: cube
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &454222
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 154222}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 7.21000004, y: -5.73999977, z: 20.7999992}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 0}
  m_RootOrder: 0
--- !u!23 &2354222
Renderer:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 154222}
  m_Enabled: 1
  m_CastShadows: 1
  m_ReceiveShadows: 1
  m_LightmapIndex: 0
  m_LightmapTilingOffset: {x: .119140625, y: .119140632, z: .48975116, w: -.000483206561}
  m_Materials:
  - {fileID: 2100000, guid: ec74a48d86d393d4ea70da2afd20af67, type: 2}
  m_SubsetIndices: 
  m_StaticBatchRoot: {fileID: 0}
  m_UseLightProbes: 0
  m_LightProbeAnchor: {fileID: 0}
  m_ScaleInLightmap: 1
  m_SortingLayerID: 0
  m_SortingOrder: 0
--- !u!1001 &100100000
Prefab:
  m_ObjectHideFlags: 1
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications: []
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 0}
  m_RootGameObject: {fileID: 154222}
  m_IsPrefabParent: 1
  m_IsExploded: 1

问题

  • 资源被打包到安装包中后,安装后的资源目录是一个只读目录,那么安装完成后怎么添加新的资源?
  • Resources.Load 函数只支持从 Resources 目录加载资源。如果更新的资源存在别的地方改怎么办?

这就是本文的姊妹篇 AssetBundle基础 存在的意义,预计12月23号左右发出。