NOTE: Some of the mechanisms discussed here are not officially documented by Unity. They can change at any time in future Unity builds. At the meantime, all researches are done with Unity 5.x.

Unity allows developers to build selected assets into asset bundles so that they can be separate from the main game and streamed to device dynamically at runtime. An asset bundle is an archive format which can contain one or more serialized Unity objects. Game developer can choose to build one bundle with many assets or many bundles each of which contains one or more assets.

It’s important for game developers to understand what will be included in an asset bundle. Knowing it will help developers properly assign assets to bundles and make efficient use of bandwidth and memory at runtime. Unity has made some clarification in the documentation below.

https://docs.unity3d.com/Manual/AssetBundles-Dependencies.html

Sometimes certain common dependencies such as a material can be referenced by many other assets in bundles. To avoid each asset bundle to contain full copies of such shared dependencies, developers will want to assign such dependencies to asset bundles as well.

Consider following assets from Low-Poly Park (available in Unity Asset Store):

  Assets
     |---Materials
     |     |---Illumin.mat
     |     \---Park_Material.mat  (assetbundlename: material)
     |
     |---Models
     |     |---NaturalPark.fbx
     |     |---NaturalPark Hovels.fbx
     |     \---NaturalParkAutumn.fbx
     |
     |---Prefabs
     |     |---Bench.prefab       (assetbundlename: bench)
     |     |---BenchTable.prefab  (assetbundlename: benchtable)
     |     |---Boat.prefab        (assetbundlename: boat)
     |     |---Bridge.prefab      (assetbundlename: bridge)
     |     |---Bush.prefab        (assetbundlename: bush)
     |     \---...
     |
     \---Textures
           |---Park_Specular.tga
           \---Park_Texture.tga

(Note that this is only a simplified scenario where the use of asset bundles in such a small project is hardly justfied).

This project has a unique property: there is only one material object. It uses texture atlas to provide materials for a variety of meshes. As suggested by Unity, we want to assign material to a separate asset bundle so that it will not be included in each asset bundle for individual models (prefabs). The textures will be automatically included in the material bundle.

Assign asset bundles to assets as described above. Add AssetBundleManager scripts to the project. Delete AssetBundleSamples. Use menu Assets -> Asset Bundles -> Build AssetBundles. The generated AssetBundles folder will look like this:

AssetBundles
  \---Windows
        |---Windows
        |---Windows.manifest
        |---material
        |---material.manifest
        |---bench
        |---bench.manifest
        |---benchtable
        |---benchtable.manifest
        |---...

The bundle “Windows” (or any other ones named after the build platform) is generated by Unity automatically. It contains an AssetBundleManifest object which can be used by a game to streamline the asset bundle download process. An example can be found in AssetBundleManager script. It does contain some knowledge about dependencies between bundles. The dependency in the manifest is based on the asset bundle names as they are built with. Unity does not seem to require the manifest or use it.

The dependency relationship that Unity uses resides in individual asset bundles. With some help from a third party asset bundle decode utility disunity, a HEX editor, an LZMA decompressor and Unity’s own binary2text utility, I am able to convert the asset bundle bench into text format.

The text file starts with a section called external references:

External References
path(1): "archive:/cab-4e1495302a9362227e5054a500aa979a/cab-4e1495302a9362227e5054a500aa979a" GUID: 00000000000000000000000000000000 Type: 0

Bench has one external reference with ID (1). The string after the path ID is the internal name Unity uses to uniquely identify asset bundles: archive:/cab-4e1495302a9362227e5054a500aa979a/cab-4e1495302a9362227e5054a500aa979a.

A MeshRender can be found in the middle of the file.

ID: 5544477923447520809 (ClassID: 23) MeshRenderer
...
...
	m_Materials  (vector)
		size 1 (int)
		data  (PPtr<Material>)
			m_FileID 1 (int)
			m_PathID -2334175533338897191 (SInt64)

Note that the mesh renderer contains a material array of one material. The material is of PPtr type, which is something Unity uses for referencing a Unity object. It has two members: m_FileID and m_PathID. m_FileID specifies whether the target object is stored locally or externally and the asset file ID if external. If m_FileID is 0, the target object is in the same asset file as the referencing object. Otherwise it should be one of the IDs in the external reference list. In this case, file ID 1 points to the first external reference, which says the asset is in a asset file known as archive:/cab-4e1495302a9362227e5054a500aa979a/cab-4e1495302a9362227e5054a500aa979a. m_PathID is an ID uniquely identifies a Unity object within the target asset file.

Decoding the material bundle and searching the path ID -2334175533338897191 yield following result:

ID: -2334175533338897191 (ClassID: 21) Material
	m_Name "Park_Material" (string)

We can now see Bench is using Park_Material as the path ID matches. But how does Unity know to look into this material bundle? That is, what is the relationship between the material bundle and the “archive:/cab-…” ID we saw earlier?

Using an hex editor, we can see that the matching “cab” ID is actually part of the material asset bundle.

00000000: 556e 6974 7946 5300 0000 0006 352e 782e  UnityFS.....5.x.
00000010: 7800 352e 362e 3166 3100 0000 0000 0003  x.5.6.1f1.......
00000020: fa0f 0000 0042 0000 005b 0000 0043 1e00  .....B...[...C..
00000030: 0100 b101 0025 b5d0 0003 f99f 0041 0e00  .....%.......A..
00000040: 0801 0000 1a00 f019 0000 0443 4142 2d34  ...........CAB-4
00000050: 6531 3439 3533 3032 6139 3336 3232 3237  e1495302a9362227
00000060: 6535 3035 3461 3530 3061 6139 3739 6100  e5054a500aa979a.
00000070: 5d00 0008 0000 0062 0b97 cb93 0e12 630c  ]......b......c.

Apparently the material bundle contains one asset file named CAB-4e1495302a9362227e5054a500aa979a which matches the external reference list in bench asset bundle.