◀ 9.39.49.5 ▶

9.4 — Your Scene Is Data: Metadata & Files

Every scene you have saved is a text file. So is every prefab, every animator, and every tile. So is the small file sitting beside each sprite that you have never once opened. Today you read those files instead of trusting the Inspector — and you find out how a scene that never writes the word "Coin" still knows exactly which coin it means.

In this lesson you will be able to answer“how do I find out what is inside a file?”
Break It Down~10 min

Open any file in your project that you did not write, and be able to say three things about it: what it holds, what it is for, and how it finds the other files it points at.

First, before anything else: cut that into parts small enough that you could look each one up on its own.

  1. Say which format the file is before you open itwhat does this part do?Read: the file-format table in this lesson's Concept Lab
  2. Read the sidecar instead of the assetwhat does this part do?Read: Step 2 of this lesson's Concept Lab, where you open a .meta file
  3. Join a reference to its asset by guidwhat does this part do?Read: the guid hunt in this lesson's Build Lab
  4. Tell the data apart from the label written on itwhat does this part do?Read: the data-versus-metadata discussion in this lesson's Concept Lab
  5. Notice when the label is older than the thing it describeswhat does this part do?Read: the stale-override hunt in Step 3 of this lesson's Build Lab, and the turret prefab you worked against in 3.1

Three of these five are habits rather than facts: check the extension before you double-click, look for the sidecar before you trust the asset, copy a guid out instead of retyping a name. The fourth is the idea the exam calls data abstraction, and it is the one worth writing down — a small label standing in for something large. The fifth is why working programmers do not trust a file just because it parses: a file describes the project as it was the last time somebody saved it, not as it is now.

The test for a finished split: point at one file in the Project window and say what is inside it in one sentence, without opening Unity. If your sentence needs the Inspector, you are describing a component rather than a file.

Your turn

Pick two of the parts above and say in one line what each one actually does.

Assets/Prefabs/Turret.prefab contains no collider of any kind, and Overworld.unity still holds two entries that set m_IsTrigger on a component id that is an anchor nowhere in the project. Who wrote those entries — a person, or Unity — and what should happen to them the next time the scene is saved?

Assets/_Scenes.meta is eight lines. Coin_Animation.png.meta is two hundred and seventy-four. Both are sidecars, both carry a guid on the second line, and both do the same job. What is the extra length in the sprite's sidecar for — and is any of it data?

The turret's Sprite Renderer stores m_SortingLayer: 4 and an id of -105541197. Nowhere in the prefab is that layer called anything at all. Where does the name of a sorting layer live, and what would you have to open to find out what 4 means?

Concept Lab ~15 min

Step 1 — look in the folder, not in Unity. Open Assets/_Scenes/ in Finder or Explorer. There are exactly three files: Start.unity, Overworld.unity and Platformer.unity. That is the whole game. Those three are also the three entries in ProjectSettings/EditorBuildSettings.asset, in that order — indices 0, 1 and 2 — which is what SceneManager.LoadScene(scene) in SceneSwitch.cs is indexing into. Nobody ever types the word "Overworld" into that code, and it still loads the right scene.

Step 2 — open one in a text editor. Not Unity. Right-click Overworld.unity and open it with TextEdit, Notepad or VS Code. It is YAML: human-readable key: value text. Every object in the scene is one block, and every block starts the same way — a Unity class id, an &, and a file id that is unique inside that one file:

--- !u!1 &6040774585044851471
GameObject:
  m_Name: Turret
  m_TagString: Enemy
  m_Component:
  - component: {fileID: 4844124505973536318}
--- !u!212 &-8321157105715108983
SpriteRenderer:
  m_Sprite: {fileID: 1391597418, guid: 465f5cb57952b46b387408a348ba8589, type: 3}
  m_SortingLayer: 4

The number after !u! is the KIND of thing, and the project uses only a handful of kinds, all of them readable in the file itself:

AnchorWhat that block is
!u!1A GameObject — the thing with a name and a tag.
!u!4 / !u!224A Transform, or a RectTransform when the object is on a Canvas.
!u!212A SpriteRenderer — the component that points at your artwork.
!u!114A MonoBehaviour — one of YOUR scripts, named by a guid rather than by a filename.
!u!95An Animator. !u!50 is a Rigidbody2D and !u!61 a BoxCollider2D.
!u!1001A prefab instance — one of the objects you dragged in from the Project window. This is the one that matters most today.

Step 3 — find your own turret. There is no turret in Platformer.unity and none in Start.unity: search either one for the word "Turret" and you get nothing. The turrets are in the Overworld, under an object named Turrets, and each one is a !u!1001 block. That block does not contain a turret. It contains a guid, a short list of changes, and nothing else — because the turret itself lives in Assets/Prefabs/Turret.prefab, and the scene is only keeping a note about it.

Step 4 — the file beside the file. Every asset in the project has a second file next to it with .meta on the end — every sprite, every script, every prefab, and every folder including _Scenes. Open Assets/Prefabs/Turret.prefab.meta. It is seven lines:

fileFormatVersion: 2
guid: 54f2fe71921990e48b811a0b3b35835f
PrefabImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:

That is the entire file. The asset next to it holds the turret; the .meta holds the turret's name as far as the rest of the project is concerned — the guid, a 32-character number that is unique across every project on earth. The .png sidecar is the same three lines followed by two hundred and seventy-one more: texture type, pixels per unit, pivot, filter mode, compression, and the rectangle of every sprite sliced out of the image. All of that is metadata — description, not content. The picture does not know any of it.

Data and metadata are two different files here — and you can prove it. Rename Shovel.png to ShovelOld.png, open Unity, and look at the player. Nothing moved, nothing went pink. The .meta kept its guid, so every reference still resolves; the filename was only ever a label on the folder listing. Now delete the .meta instead, and every scene that pointed at that sprite loses its connection, because the guid those references were written against is gone. The identity of an asset is not its name, and it is not its pixels. It is the number in the sidecar.

Step 5 — follow one reference all the way. This is the whole lesson in four lines. In Overworld.unity, search for stripped. You will find blocks like this one:

--- !u!4 &861464021 stripped
Transform:
  m_CorrespondingSourceObject: {fileID: 4281311786053241907, guid: 69c7343f050914c7787bbbe42c07b5b8, type: 3}
  m_PrefabInstance: {fileID: 186509170}

Read it as a sentence: the Transform you are looking for is not written here. It lives in the asset whose guid is 69c7343f050914c7787bbbe42c07b5b8, as the object numbered 4281311786053241907 inside that asset. Now go and check it. Assets/Prefabs/Coin.prefab.meta carries that exact guid, and Assets/Prefabs/Coin.prefab contains --- !u!4 &4281311786053241907. You have just walked from a scene, through a sidecar, into a prefab, using nothing but a number. That is what serialization means in Unit 9: the object in memory has been written down as text, and the pointer between two objects has been written down as a guid instead of a memory address.

Socratic

A prefab is a file, and a scene holds instances of it. Explain "prefab as data abstraction": what does the prefab FILE hide from the scene, and what does its guid GUARANTEE that a file path cannot? Test it — rename a sprite and count what breaks, then find a reference written by guid and count again.

Build Lab ~20 min

Step 1 — change a value without opening Unity. Make a copy of Overworld.unity first. Then find the block --- !u!1001 &208023028 — one of the two turret instances — and read its override list. One entry changes m_LocalPosition.x to 15.13. Now open Assets/Prefabs/Turret.prefab and read the turret's own root Transform, --- !u!4 &4844124505973536318: m_LocalPosition: {x: 0, y: 0, z: 0}. The prefab says the turret is at zero; the scene says this turret is at 15.13. That is what an override is — a value on the instance, not on the asset.

Now change 15.13 to something absurd, close Unity first if it is open, reopen the scene, and press Play. The turret has moved. You edited the game without opening the Inspector, which is the same power as the palette edit from 9.2, one level deeper.

Step 2 — diff a playtest edit. Close Unity. Copy Overworld.unity again, open Unity, move three objects, save, close. Now compare the two files — VS Code's compare, or just search for the changed numbers — and notice how small the diff is. Each object you moved is a handful of changed m_LocalPosition values inside one !u!1001 block, one number per axis. Your entire semester of level design is that readable.

Step 3 — find the metadata that is out of date. Stay in the turret instance and read the first entry in the same override list:

- target: {fileID: -28657926046577547, guid: 54f2fe71921990e48b811a0b3b35835f, type: 3}
  propertyPath: m_IsTrigger
  value: 0

That says: in the asset whose guid is 54f2 — the turret prefab — find the object numbered -28657926046577547 and set its m_IsTrigger to 0. So go and find it. Search Turret.prefab for 28657926046577547 and you get zero hits. Search the whole project and you get one hit: this line, the one looking for it. There is no such component. The prefab has six anchors and none of them is that number, and the prefab holds no collider at all — so an entry that claims to be setting a collider's trigger flag is describing an object that does not exist. The Player instance carries the same kind of ghost: m_GravityScale, aimed at a number that is an anchor nowhere in the project.

This is not a bug you have to fix, and it is the best thing in the file. Somebody edited these files as text — the prefabs and the scenes — and never re-saved them in Unity. The scene still remembers the version of the prefab it was written against, and that version had a collider. Unity, when it next opens and saves that scene, will quietly drop the dead entry, because Unity reads the prefab to find out what exists. A text file cannot. That is the difference between a file that is true and a file that is merely old, and it is why the same scene file behaves differently after somebody re-saves it.

Checkpoint — before moving on, you must be able to:

Reference Docs

Need a deeper explanation? These pages cover the same concepts:

Next: 9.5 — Datasets: Insights from Playtest Data

0/5 answered

Answers save on this device as you type. At the end of class, click Download and upload the file to the Canvas assignment.

Saved on this device only — the Dashboard tracks your progress.