Unity工程里的那些東西

1、特殊文件夾(unity doc : Special Folders)

Unity工程根目錄下,有三個特殊文件夾:Assets、Library、ProjectSettings
  • Assets

Unity工程中所用到的所有Asset都放在該文件夾中,是資源文件的根目錄,很多API都是基于這個文件目錄的,查找目錄都需要帶上Assets,比如AssetDatabase。

  • Library

Unity會把Asset下支持的資源導入成自身識別的格式,以及編譯代碼成為DLL文件,都放在Library文件夾中。

  • ProjectSettings

編輯器中設(shè)置的各種參數(shù)


參數(shù)
下面都是存在Assets目錄下的文件的了。
  • Editor

為Unity編輯器擴展程序的目錄,可以在根目錄下,也可以在子目錄下,只要名字叫“Editor”,而且數(shù)量不限。Editor下面放的所有資源文件和腳本文件都不會被打進包中,而且腳本只能在編輯器模式下使用。一般會把擴展的編輯器放在這里,或只是編輯器程序用到的dll庫,比如任務(wù)編輯器、角色編輯器、技能編輯器、戰(zhàn)斗編輯器……以及各種小工具。

  • Editor Default Resources

名字帶空格,必須在Assets目錄下,里面放編輯器程序用到的一些資源,比如圖片,文本文件等。不會被打進包內(nèi),可以直接通過EditorGUIUtility.Load去讀取該文件夾下的資源。

  • Gizmos

Gizmos.DrawIcon在場景中某個位置繪制一張圖片,該圖片必須是在Gizmos文件夾下。

void OnDrawGizmos() {
        Gizmos.DrawIcon(transform.position, "0.png", true);
    }

OnDrawGizmos是MonoBehaviour的生命周期函數(shù),但是只在編輯器模式下每一幀都會執(zhí)行。Gizmos類能完成多種在場景視圖中繪制需求,做編輯器或調(diào)試的時候經(jīng)常會用到,比如在場景視圖中繪制一條輔助線。(用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,它會根據(jù)平臺返回正確的路徑,如下:

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

隱藏文件夾和文件
以"."開頭
以"~"結(jié)尾
名字為"cvs"
擴展名為".tmp"

Asset(doc

An asset is representation of any item that can be used in your game or project. An asset may come from a file created outside of Unity, such as a 3D model, an audio file, an image, or any of the other types of file that Unity supports. There are also some asset types that can be created within Unity, such as an Animator Controller, an Audio Mixer or a Render Texture.

asset就是游戲中所用的資源,可以是用其它軟件創(chuàng)建的,如3D model、audio、image等,和一些unity可創(chuàng)建的,如animator、audio mixer、render texture...

  • 一些通常的Asset類型

Image: 支持絕大多數(shù)的image type,例如BMP、JPG、TIF、TGA、PSD
Model:eg、.max、.blend、.mb、.ma,它們將通過FBX插件導入。或者直接在3D app導出FBX放到unity project中
Mesh and Animations:unity支持絕大多數(shù)流行的3D app的model(Maya、Cinema 4D、3ds Max、Cheetah3D、Modo、Lightwave、Blender、SketchUp)
Audio Files:如果是非壓縮的audio,unity將會根據(jù)import setting壓縮導入(更多
Other:

  • Asset Store

里面有很多免費和收費的插件,可以供開發(fā)者下載使用。

下載的第三方工具是以package文件存在,導入package:


package.png
  • 導入

unity會自動導入Asset目錄下的資源,可以是unity支持的,也可以是不支持的,而在程序中用到的(比如二進制文件)。

當在Asset下進行保存、移動、刪除等修改文件的操作,unity都會自動導入。

  • 自定義導入

導入外界的unity可識別的Asset時,可以自定義導入設(shè)置,在工程中點擊資源文件,然后Inspector視圖中就會看到相應的設(shè)置:


Atlas Import Setting.png
Plugin Import Setting.png
  • 導入結(jié)果( doc

導入資源之后,除了要生成.meta文件,unity并不是直接使用這些資源的,而是在導入的過程中,生成了unity內(nèi)部特定的格式(unity可識別)文件在游戲中使用,儲存在Library目錄下,而原始資源不變,仍然放在原來位置。當然,每次修改原始文件,unity都會重新導入一次,才能在unity中看到改過之后的樣子。

正因為Library存放了導入資源的結(jié)果,所以每次刪除Library或里面某個文件,都會讓unity重新導入相應的資源(生成內(nèi)部格式),但對工程沒有影響。


library.png

最終那些資源的導入結(jié)果就在metadata文件夾里

“the results of the import process are stored in a folder named for the first two digits of the Asset’s File GUID. This folder is stored inside the Library/metadata/ folder. The individual Objects are serialized into a single binary file that has a name identical to the Asset’s File GUID.”
import的結(jié)果存儲在Library/metadata/文件夾下,并且把File GUID的前兩位bit作為文件夾名,以File GUID作為文件名字。

資源存放.png
  • .meta文件

Asset中的所有文件、文件夾,經(jīng)過unity的導入過程后,會為每個都生成一個.meta文件,這個文件是unity內(nèi)部管理文件的重要內(nèi)容,里面記錄著一些信息。

你知道unity是怎么管理資源依賴關(guān)系的嗎?可以試著更改一個掛在prefab上的腳本的目錄或者名字,而這些prefab依然可以正常的調(diào)用那些腳本。

unity在第一次導入新文件的時候,會生成一個Unique ID,用來標志這個asset,它就是unity內(nèi)部用來區(qū)分asset的。Unique ID是全局唯一的,保存在.meta文件中。

在unity中資源間的依賴關(guān)系引用都是用Unique ID來實現(xiàn)的,如果一個資源丟失了.meta文件,那依賴它的資源就找不到它了。

If an asset loses its meta file (for example, if you moved or renamed the asset outside of Unity, without moving/renaming the corresponding .meta file), any reference to that asset will be broken. Unity would generate a new .meta file for the moved/renamed asset as if it were a brand new asset, and delete the old “orphaned” .meta file.

For example, in the case of a texture asset losing its .meta file, any Materials which used that Texture will now have no reference to that texture. To fix it you would have to manually re-assign that texture to any materials which required it.

In the case of a script asset losing its .meta file, any Game Objects or Prefabs which had that script assigned would end up with an “unassaigned script” component, and would lose their functionality. You would have to manually re-assign the script to these objects to fix this.

.meta文件內(nèi)容如下,包括Unique ID和Import Setting的內(nèi)容


meta.png

腳本

unity支持三種腳本語言,分別是C#、JavaScript、Boo,最常用的是前兩種,當然還有后來擴展的支持Lua腳本的庫(slua、ulua)。


生成的對應的工程.png
  • 1.編譯順序

編譯順序的原則是在第一個引用之前編譯它,參考官網(wǎng)文檔可以知道,Unity中的可以將腳本代碼放在Assets文件夾下任何位置,但是不同的位置會有不同的編譯順序。規(guī)則如下:

The phases of compilation are as follows:
Phase 1: Runtime scripts in folders called Standard Assets, Pro Standard Assets and Plugins.
Phase 2: Editor scripts in folders called Editor that are anywhere inside top-level folders called Standard Assets, Pro Standard Assets and Plugins.
Phase 3: All other scripts that are not inside a folder called Editor.
Phase 4: All remaining scripts (those that are inside a folder called Editor).

(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.編譯結(jié)果:

項目工程文件夾中會生成類似如下幾個文件, 按順序分別對應著上述四個編譯順序:(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

內(nèi)容包括了Plugin導入設(shè)置、怎樣創(chuàng)建使用兩種Plugin、怎樣利用底層渲染接口以及一些基礎(chǔ)知識。

在打包的時候,會把plugin里面的各種庫,拷貝到包體中相應的位置(不同平臺不一樣,具體在可以把工程分別打成幾個平臺的包)


win平臺

這是win32平臺的包,Managed里面放置的托管庫,Mono里面放的是mono的庫,Plugins是平臺庫(native plugin)

分平臺打包,就需要對不同平臺的plugin區(qū)分,方法是在Plugins目錄下建立相應平臺的文件夾,unity在為不同平臺打包的時候,除了會將相應平臺的plugin里的腳本編譯成Assembly-CSharp-firstpass.dll,還會把已經(jīng)是dll、so等庫直接拷貝到包內(nèi)相應位置。
Plugins/x86:win32位平臺plugin
Plugins/x86_64:win64位平臺plugin
Plugins/Android:Android平臺
Plugins/iOS:iOS平臺

Object

UnityEngine.Object是所有類的基類,它描述了Asset上使用的所有resource的序列化數(shù)據(jù),它有幾個重要的派生類:GameObject,Component,MonoBehaviour

  • GameObject

GameObject是組件的容器,所有Component都在可以掛在上面,Unity以組價化思想構(gòu)建,所有功能拆分成各個組件,需要某個功能只需掛上相應的組件,組件之間相互獨立,邏輯互補交叉。當然組件式開發(fā)也有最大的弊端就是組件之間的交互。

  • Component

Component作為組件的基類,unity中有大量的組件,Transform、Renderer、Collider、MeshFilter都是組件。

  • MonoBehaviour

開發(fā)時創(chuàng)建的腳本,需要掛在GameObject上的腳本都是繼承自MonoBehaviour。

  • ScriptableObject

自定義可被Unity識別的資源類型,可打成AssetBundle,可通過Resources or AssetBundle加載。

序列化

  • Asset和Object的關(guān)系

Object作為Asset的序列化數(shù)據(jù),比如以Texture導入一張圖片,那么就用Texture對象記錄描述了該圖片。
Asset可能有多個Object,比如prefab的GameObject上掛著多個組件,這樣Asset和Object就是一對多的關(guān)系。那么問題來了,同一個Object怎么區(qū)分分別掛在不同GameObject上的對象的?等等,這里是一定要區(qū)分的,因為它們要包含序列化數(shù)據(jù)(在Inspector視圖設(shè)置的),而不是在游戲運行中再new。

  • Class ID 和 File ID(object id)

先梳理一下關(guān)系,unity通過guid找到asset,其中asset上可能又掛了很多組件,每個組件又對應著一個class,而在序列化的時候是對象。Class ID是unity定義好的(傳送),F(xiàn)ile ID是為對象生成的id,也就是說,我用guid + (class id 可有) + file id 就能確定某個資源上的組件對象。

  • YMAL

是一種標記語言,如果不了解語言格式可以看網(wǎng)站。

  • Text-Based Scene Files

和二進制文件一樣,unity還提供了基于文本的場景文件,使用YAML標記語言,通過文本描述了asset和object組件之間的關(guān)系是怎么關(guān)聯(lián)、保存數(shù)據(jù)等。

通過設(shè)置Edit -> Project Setting -> Editor -> Asset Serialization -> Force Text,我們可以查看所有Object信息了。


text-based.png

下面是一個GameObejct的YAML document:
<pre>
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !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: 1000010512509832}
m_IsPrefabParent: 1
--- !u!1 &1000010512509832
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 4
m_Component:

  • 4: {fileID: 4000012302714536}
  • 33: {fileID: 33000011309778356}
  • 23: {fileID: 23000013678005954}
  • 114: {fileID: 114000012372194584}
    m_Layer: 0
    m_Name: Cube
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!4 &4000012302714536
    Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 1000010512509832}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: 0, z: 0}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
    m_Children: []
    m_Father: {fileID: 0}
    m_RootOrder: 0
    </pre>

第三行的字符串“--- !u!1001 &100100000”,“!u!”后面的“1001”是Object的Class ID,“&”后面的“100100000”是File ID。
YAML Class ID Reference

Class ID.png

接著第四行是Prefab,是Class Name;下面“m_”開頭的是它的序列化屬性,請看“m_RootGameObject”,記錄著Prefab對象的根節(jié)點的GameObject對象,繼續(xù)看后面“{fileID: 1000010512509832}”,file ID指向的剛好是第14行定義的GameObject對象;第20行m_Component屬性,可以看出gameObject上掛了四個組件,通過前面的Class ID就可以查到是什么組件了。

Instance ID

在前面已經(jīng)介紹了GUID、Class ID、File ID,先做個小結(jié)。Unity通過GUID找到asset文件,以至于我們可以隨意更改asset文件的位置,但是.meta文件丟失就會導致找不到相應的資源,最常見的就是丟失腳本;接著在游戲中加載某個資源的時候,通過File ID找到組件的Object,如果Object沒有被加載就找不到,則通過File ID找到數(shù)據(jù)源,通過Class ID找到類,然后實例化對象,初始化序列數(shù)據(jù),并分配Instance ID,Object就加載好了。

但是每一個資源,這樣每一次加載都需要對GUID和File ID遍歷查找比較判斷對應的Object是否加載,這樣就會帶來性能問題。所以基于這個原因,所以利用GUID和File ID生成一個Instance ID,在Unity內(nèi)部維護了一個Instance ID的映射緩存來標識各個Object,每當有新的Objects添加到緩存中時,Instance ID以簡單的單調(diào)遞增的方式進行賦值。

另外Instance ID的生命周期和Object的創(chuàng)建銷毀是一致的。

參考文章

特殊文件夾的編譯順序
Unity腳本執(zhí)行順序和編譯順序
Unity文件夾
Unity文件夾
Special Folder
unity資源

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容