Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

FBX Submesh FileIDs

Discussion in 'Asset Importing & Exporting' started by OneTwoApp, Aug 10, 2020.

  1. OneTwoApp

    OneTwoApp

    Joined:
    Nov 3, 2016
    Posts:
    1
    Hi Everyone,
    I'm working a tool for unity which is required to work on scene meta files(.unity files).
    MeshFilter component stored in scene meta file like this.
    scene.unity file -->>
    Code (yaml):
    1. MeshFilter:
    2.   m_ObjectHideFlags: 0
    3.   m_CorrespondingSourceObject: {fileID: 0}
    4.   m_PrefabInstance: {fileID: 0}
    5.   m_PrefabAsset: {fileID: 0}
    6.   m_GameObject: {fileID: 5745507458705303802}
    7.   m_Mesh: {fileID: 3921568967233161584, guid: 87d4120f450944f46957230d35b9b28e, type: 3}
    I cant find how fileID generated for submesh. As I know fileIDs is generating for monoscript with MD4 hash and first 4 bytes of that hash. Hashing algorithm take "s\0\0\0" + namespace + className as a input.

    What is this inputs for Fbx submeshes? name of the submesh is not worked?
    Thank you.
     
  2. cgDoofus

    cgDoofus

    Joined:
    Jun 15, 2021
    Posts:
    48
    Sorry for bumping this old thread, any answer for this?
     
  3. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    The whole Mesh fileId hashing changed a lot in the past few years.
    Old fbx files (Unity 2019.2 and before), that still have their old meta files, used a sequential hash that didn't use the name of the mesh and only its type + an incremental number. Their fileIds are stored in the fbx metafile to keep them as consistent as possible between imports (the numbers starting with 43 inside the fileIDToRecycleName array in the metafile)
    The new system, for any fbx file added for the first time in Unity 2019.3 and newer versions, is using xxHash from a string formed this way:
    "Type:NameSpace::TypeName->MeshName"
    For sub meshes, it will be the same with a specific name built this way: "MeshName_MeshPartX" with X being the index of the submesh.

    So if you want to generate them by yourself, with meshs prior to Unity 2019.3, you're probably out of luck. but on any recent version, with recent assets, you can use an xxHash library (I don't think the internal one is exposed to the c# in Unity), and the hash string to compute for submeshes should always be something like "Type:Mesh->yourmeshname_MeshPart0" for the first submesh for example.

    However, if you can load that Mesh and submeshes, you can also call AssetDatabase.TryGetGUIDAndLocalFileIdentifier which will give you both the guid and fileId of any asset and subasset.
     
  4. cgDoofus

    cgDoofus

    Joined:
    Jun 15, 2021
    Posts:
    48
    Thanks for your answer! really insightful. I've tried this xxHash implementation, however I can't seem to manually recreate the id generated in unity, for instance for a mesh named Cube I tried
    XXH64("Type:Mesh->Cube_MeshPart0", strlen, 0)
    and casting it to signed int64 but that doesn't seem to match what unity produces

    Is there a documentation on how game objects and components fileids are generated from fbx files persistently?
     
    Last edited: Jul 9, 2022
  5. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    After a second check, we always append a 0 at the end of the string, for some reason...
    So the correct string would be Type:Mesh->Cube_MeshPart00 for the first submesh.

    Also, I feel like there may be confusion on what a submesh vs. a mesh is (and that's definitely my fault for misinterpreting the original post, which I think was talking about submesh as in subassets of an FBX file rather than actual submeshes.)

    If you're importing an fbx file, it will produce meshes, maybe multiple of them, but they are still simple meshes and use only their mesh name in the string building (Type:Mesh->Cube0 for example).
    When these meshes are too big (too many vertices) they will be split into several submeshes in which case they're going to use the MeshPartX substring (which would be Type:Mesh->Cube_MeshPart00 if your cube get split in several submeshes)

    To that question, I don't think we have any official documentation for it unfortunately... Mostly because none of it is really exposed and officially supported (I don't know why/when we could change that without notice)
     
  6. cgDoofus

    cgDoofus

    Joined:
    Jun 15, 2021
    Posts:
    48
    that worked!! could've never guessed this haha
    Yes I think the original post (and me) meant sub-assets, I'm wondering though, is a mesh with multiple materials also split into sub meshes?
    That's unfortunate, I think most of unity's parsing is logical and can be reproduced without special knowledge of hashing, string formatting etc except for the imported assets part, though if I had to take a guess, would the game object and transform be more like this?
    Type:GameObject->[object name]0
    Type:Transform->[object name]0
    or is it a different format? or namespaces?
     
  7. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    Yes, it is, you'll have one submesh per material.

    GameObjects and Components are a bit more complicated. The name becomes the full path of the GameObject in the hierarchy, the same for native components with an added "/ComponentType" at the end. MonoBehaviours also has special handling which seems to be "/MonoBehaviour-FullCSharpClassName" (I'm not sure of the format here).
    In the ModelImporter, we are also always starting the names with "//RootNode" and the first object is forced to be named "root" due to old compatibility and upgrade code.
    So it will look like
    Type:GameObject->//RootNode/root0
    for the root of the GameObject created in a ModelImporter, and
    Type:Transform->//RootNode/root/Transform0
    for its Transform component.

    And again, this is for new fbx files imported after Unity 2019.3, if your asset is older than that, then it's a whole different story.
     
  8. cgDoofus

    cgDoofus

    Joined:
    Jun 15, 2021
    Posts:
    48
    So after some inspection, it seems that the _MeshPartID0 suffix is referenced in the mesh renderer, but the mesh filter's referenced mesh is still the "parent" with no submesh suffix, which makes sense as a mesh filter shouldn't hold more than one mesh. Interesting.
    Awesome! perfect thank you.
    Though I personally think it's a bit counter intuitive to not factor in the file path for these "sub file" hashes, sure that might make it more susceptible to collisions but it'd make more sense from a data oriented standpoint to have one "world" with unique entities for everything rather than having a world with sub worlds. Just some personal thoughts
     
  9. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    Doing so would prevent references for staying the same when an asset name is changed or moved in your project. This is also why have a guid in the meta file which is used for the reference instead of a direct path to the asset. So you can reference it once, then move it anywhere, and the created fileIDs and guid will stay consistent.
     
  10. unity_zY0DtqQH1lTrOQ

    unity_zY0DtqQH1lTrOQ

    Joined:
    Aug 23, 2019
    Posts:
    3
    I cannot get it to work :( I am also building an asset pipeline and am struggeing with the FileIDs.

    I have a FBX file named "ukopeijs_LOD5", inside a Mesh named "Aset_nature_rock_M_ukopeijs_LOD5".
    So to my understanding I would have to create a xxHash with "Type:Mesh->ukopeijs_LOD5_MeshPart00" in order to get the FileID of the Aset_nature_rock_M_ukopeijs_LOD5 mesh?
    No matter what I try, I always get a different hash.
     
  11. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    The name of the fbx doesn't matter here, it's the mesh name. I think the ID should be "Type:Mesh->Aset_nature_rock_M_ukopeijs_LOD50", unless the mesh is being split into submeshes in which case you'd have multiple meshes with ids "Type:Mesh->Aset_nature_rock_M_ukopeijs_LOD5_MeshPart00", "Type:Mesh->Aset_nature_rock_M_ukopeijs_LOD5_MeshPart10", etc...
     
  12. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    By the way, I'm not sure what you are all trying to do with fileId reconstruction like that, but I'd heavily recommend not to use that too much... These are some internal APIs that we can change whenever we want without notice and any tool based on that may start failing at any point or another.

    The only reason I'd make a tool in Unity using that is to fix a large range of assets in a project that I broke in one shot and then discard the tool because I'd want it to be fast on a large project, and it'd be my last resort to try get things back together.
    If you didn't try to first remap ids using official APIs like TryGetGUIDAndLocalFileIdentifier, maybe refrain a bit from diving this much into sketchy string hash try and errors!
     
  13. cgDoofus

    cgDoofus

    Joined:
    Jun 15, 2021
    Posts:
    48
    For me I'm doing an external tool that mimics unity to visualize simple scenes, it's more of a fun project/proof of concept so I don't mind future compatibility that much. That said though I think it'd be handy to have this be more than an internal API, that's the main point of it being in a text based format right?
     
  14. cgDoofus

    cgDoofus

    Joined:
    Jun 15, 2021
    Posts:
    48
    different beast of a question :)
    I was able to fetch file IDs of mesh renderers from fbx files using the same formula used for Transform, however if that fbx PrefabInstance is inside a unity prefab, the mesh renderer there would be referenced with a different fileID, so I'm guessing that that mesh renderer fileID is generated relative to the prefab it's in? If so any formula for that?
    This would also apply to overriding a transform or whatever of an fbx sub object if that sub object is inside a unity prefab
     
  15. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    We're using text format to make it easier to merge assets/figure out what seems to be wrong by hand when something happens.
    Shipping a public API has a very heavy cost given the number of projects and users we have, and I don't think we will ever expose with a public API something that deep in our import system.
     
  16. bastien_humeau

    bastien_humeau

    Unity Technologies

    Joined:
    Jun 14, 2017
    Posts:
    191
    The ModelImporter is using the
    //RootNode/
    as a prefix for the names in the hierarchy, and it looks like the Prefab system doesn't.
    So your object name should be something like
    Type:Transform->prefabname/rootname0
    for the transform on the root object.