Search Unity

What does "type: 3" mean in Unity scenes/prefabs' YAML?

Discussion in 'Scripting' started by ModLunar, Jul 18, 2022.

  1. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    I'm writing a script to help myself replace all occurrences of a MonoBehaviour or ScriptableObject type to another type, and am gonna see if a basic "Replace All" in the .unity and .prefab files works.

    In a scene or prefab file, a MonoBehaviour might look something like this:
    Code (CSharp):
    1. --- !u!114 &1267931007055091527
    2. MonoBehaviour:
    3.   m_ObjectHideFlags: 0
    4.   m_CorrespondingSourceObject: {fileID: 0}
    5.   m_PrefabInstance: {fileID: 0}
    6.   m_PrefabAsset: {fileID: 0}
    7.   m_GameObject: {fileID: 1267931007055091521}
    8.   m_Enabled: 1
    9.   m_EditorHideFlags: 0
    10.   m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
    From the UnityEngine C# API, I see that the guid and fileID are the asset's guid and localId from AssetDatabase.TryGetGUIDAndLocalFileIdentifier(...).

    However, what does type: 3 mean, and what values are expected there/what do they correspond to?
    I've seen type: 0 and type: 2, but nothing else.
     
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,011
    Well, we don't know for sure. However it's most likely simply the "format version" of this asset reference. References inside a yaml file could reference different things. In this case the 115 of the fileID indicates the type MonoScript as you can see here. So the internal "m_Script" reference directly references the TextAsset / MonoScript instances that represents the script asset indentified by the guid. Though references can be internal references (like
    {fileID: 1267931007055091521}
    in your snippet).

    I'm not sure if the other types are just "older" serialized asset reference versions which may be handled differently. Since Unity does support scripts loaded from a managed assembly, there is no direct file for every MonoBehaviour class in the assembly. This was just an example of the top of my head. It may not even be related to this. AFAIK the type of an asset reference is not really documented anywhere. Unity's documentation on it's yaml format is not that verbose.
     
    ModLunar likes this.
  3. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    Oh awesome, thanks for the explanation and docs links!
    Then it seems like if I'm doing text replacement, I should be fine just keeping the "type" the same
     
  4. LucasSupportSquare

    LucasSupportSquare

    Joined:
    Oct 14, 2020
    Posts:
    6
    I'm also looking into asset serialization and stumbled upon this blog post from just a few days ago. I think this answers your question :)

     
  5. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    LucasSupportSquare likes this.
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,011
    :) Awesome. I'm wondering if this thread actually kicked off the blog post in the first place :D
     
    ModLunar likes this.
  7. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    Ah funny to be back,
    I found an example today in one of my project scene files:

    Code (CSharp):
    1. --- !u!114 &2044988749
    2. MonoBehaviour:
    3.   m_ObjectHideFlags: 0
    4.   m_CorrespondingSourceObject: {fileID: 0}
    5.   m_PrefabInstance: {fileID: 0}
    6.   m_PrefabAsset: {fileID: 0}
    7.   m_GameObject: {fileID: 2044988747}
    8.   m_Enabled: 1
    9.   m_EditorHideFlags: 0
    10.   m_Script: {fileID: 1331599490, guid: e82b514becad6484bbf6f029b99d927e, type: 3}
    11.   m_Name:
    12.   m_EditorClassIdentifier:
    13.   requireAdditionalScene: 1
    14.   sceneBuildIndexToLoad: 1
    I used to bring this big DLL of compiled C# code with me on every project, until I got myself into dependency hell and couldn't make a Unity project without it.

    When trying to remove my DLL out of my projects and replace it with the source code .cs files,
    I've always noticed how it's "impossible" by normal means to migrate all the references, from C# Scripts in a .dll file to reference source C# Scripts (.cs files).

    Now I see why in the YAML!
    They're different types of references, because Unity has to process the .dll and generate the MonoScripts under your Library folder. This gives the GUID of my .dll file, where it says:

    guid: e82b514becad6484bbf6f029b99d927e

    Then, the fileID is saying that UNDER that .dll file, there's an asset (C# script) inside given by:

    fileID: 1331599490

    And then the following just lets Unity know this asset is loaded from the Library folder (type 3) instead of the Assets folder (type 2):

    type: 3
     
    Bunny83 and mgear like this.
  8. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,011
    Note that there is no "C# script" under a DLL since a DLL is already compiled. However you are right that Unity generates "sub assets" under the DLL which represent the referencable classes inside that dll. Those should also be shown in the project view as sub assets under the imported DLL.
    If you want to migrate you probably want to create a separate project where you prepare and import the source files, let Unity generate the meta files and create a map which asset ID belongs to which class. In the original project you essentially do the same thing for all the classes which are provided through the DLL. When you have the mapping you could perform a plain search and replace across your scenes / prefabs.

    It's certainly a bit of work. I guess it may be possible to create some editor scripts which could help in that process.
     
    ModLunar likes this.
  9. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    Minor detail, but I'm curious what would be the correct term to call them technically? (instead of "C# script")

    Also re: the migration, that would be an awesome editor workflow improvement!
    Luckily though, I use the Package Manager nowadays with my own Scoped Registry / plain .cs source files, so whew. Done with this for the most part (except when going back to really old projects I haven't touched in a while).
     
  10. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,011
    Well that's a bit difficult :) From a technical point of view it would still be a MonoScript instance. While a MonoScript is a TextAsset, I doubt that a MonoScript that is loaded from a DLL actually contains any C# code since there is no source code. So it most likely just acts as an empty placeholder. So you can get the actual class type (GetClass()) and reference its type which is your case.

    Yes, if you just have a couple of instances (MonoBehaviours and ScriptableObjects), migrating manually isn't that complicated. Note that you can even manually replace script types in the inspector when you switch the inspector into debug mode. So component instances which have a "Missing MonoBehaviour" could be replaced by dragging the new / replacement type onto the type / script field.
     
    ModLunar likes this.