feat: Hierarchical Model Importer
This PR adds an “Split hierarchy” workflow for model import: when enabled, Stride imports one Model per mesh (named after the mesh) and automatically generates a Prefab that mirrors the FBX node hierarchy. When disabled, the import produces a single combined Model (no “(All)” suffix).
What’s in this PR-
Split hierarchy checkbox in Add asset → 3D model dialog.
Remembers last value per project.
Behavior (per mode)
Split hierarchy = ON
Imports N Model assets (one per mesh) named: "<ModelName>-<MeshName>" (sanitized; auto-uniquified with -1, -2, …).
Creates a Prefab named "<ModelName> Prefab" that replicates the FBX hierarchy (one Entity per node, correct parent/child relationships).
Each Entity that hosts a mesh gets a ModelComponent referencing the corresponding per-mesh Model.
Each per-mesh Model keeps only the material(s) it actually uses\
Split hierarchy = OFF
Imports a single Model named exactly "<ModelName>"
@noa7 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
@dotnet-policy-service agree [company="{your company}"]Options:
- (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@dotnet-policy-service agree
- (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@dotnet-policy-service agree company="Microsoft"Contributor License Agreement
@dotnet-policy-service agree
Looks like materials are not handled properly: every individual object is set to the same material.
The prefab's hierarchy is almost right, there is an additional RootNode created and a weird parenting issue, see the following comparison:
Here's the file I used for testing - this is not CC0, do not use in projects.
Thanks for sharing the test file. I’ve checked in updates, and both issues are now fixed:
- The prefab in Stride now exactly replicates the FBX hierarchy as seen in Blender- no extra "RootNode"
- Material assignments on individual sub-meshes remain intact after import
@Eideren
We're back to the previous issue with the materials, we need to only have the materials that are assigned to an object on that object, not every material that was contained in the original scene.
Also, the pivot position for individual models is not retained, they all have their pivot set to the origin instead of wherever it actually is in the file.
are you on latest? it imports fine my side
The vertices are at the right position in world space, but each mesh's pivot point is not right below the model, like it is in the file, it is set to the origin.
For example, if you only place the bookends model in the world, setting its entity's position to 0,0,0 should center the object around the origin
The prefab entity for a given model should have its position moved to match wherever the model is in the imported file, the model asset itself should not have any transformation applied.
Makes sense, thanks for pointing out, This is now fixed.
With this latest-
- Only the material applied on mesh are visible in inspector
- The relative positiong of each item in prefab based of entity data in scene by storing each mesh's TRS data at its nodeinfo object that prefab is constructed with. And each mesh pivot in scene matches to that in source model
@Eideren
You haven't thoroughly gone through the LLM's work there it seems, there's a fairly large amount of redundant logic, and comments that are clearly targeted at someone interacting with an LLM, not at describing the logic being implemented.
I'm okay with reviewing someone's work, not going over what an LLM spit out, that is your burden to carry - and you're definitely capable of that, I have seen you write better stuff than this.
I haven't gone through the whole thing yet, but do go over your entire PR and clean things up, there's a lot of low hanging fruits I have not marked.
You could also look into using/enabling nullable, there's a bunch of null checks and tests that are redundant or definitely should throw in the null case.
Got it. I was focusing on getting it fully functional before moving on to cleanup and optimization, since the prefab generation feature is a bit tricker than I anticipated. I’ve removed any mechnical commets. Committed the latest version with fixes and a cleaner codebase @Eideren
Throws in ResetMaterialsOnPrefabItems when importing into a folder, that method definitely required a second cleanup pass anyway.
How about you replace those strings and pass references or ids around, this goes for other methods too. So many string manipulation and lookups, it's no wonder the whole thing throws if we so much as look at it.
No more string manipulations by storing source mesh name variable in ModelAsset, checked in latest @Eideren
Most of my comments have not been addressed, moving this to draft while you take care of those. Feel free to set it to ready once it is actually ready for review.
Most of my comments have not been addressed, moving this to draft while you take care of those. Feel free to set it to ready once it is actually ready for review.
Can you tell which ones specifically, I gone through all and made necessary cahnges!
Those listed below the following message https://github.com/stride3d/stride/pull/2898#issuecomment-3323404313
Those listed below the following message #2898 (comment)
Its importing fine for me in a folder on latest and have removed strig manipulations?
Yes, I got that, but you haven't gone through the review I made below the message I linked here https://github.com/stride3d/stride/pull/2898#issuecomment-3323404313
This stuff:
Yes, I got that, but you haven't gone through the review I made below the message I linked here #2898 (comment) This stuff:
I really can't see that list my side of github :)
Ah, okay, my bad, that's on me. Give me a sec.
Removed the filename-based mesh selection and made it an explicit part of the asset data. The chosen mesh now comes from ModelAsset.MeshName, which is passed via ModelAssetCompiler > ImportThreeDCommand to MeshConverter.KeepOnlyMeshByName. The old DecideKeptMeshIndexFromOutput logic is removed @Eideren
Did you test your changes ?
Yes tested with the room model file
On Sun 12. Oct 2025 at 20:20, Eideren @.***> wrote:
Eideren left a comment (stride3d/stride#2898) https://github.com/stride3d/stride/pull/2898#issuecomment-3394971751
Did you test your changes ?
— Reply to this email directly, view it on GitHub https://github.com/stride3d/stride/pull/2898#issuecomment-3394971751, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF5T3BZKSPMEKIHDVGZGS2T3XKEXHAVCNFSM6AAAAACGW4SEGGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTGOJUHE3TCNZVGE . You are receiving this because you were mentioned.Message ID: @.***>
Well, not sure what you did test, but I can still repro the naming issue I mentioned
@Eideren can you point which naming issue?
The one I mentioned there as I said https://github.com/stride3d/stride/pull/2898#discussion_r2392252314 - Changing the name of a model asset in the editor changes the actual mesh that gets imported
My mistake, overlooked that part. I’ve checked in updates, storing mesh ID as a key pointer in ModelAsset, which is set only once at time of creation and remains unchanged on renaming etc. @Eideren
If I select this option from the context menu, the model has a bunch of new entries created for its materials instead of just the ones used
Fixed. It still reimports the mesh upon update from source but will not add extra materials @Eideren
If a model has multiple materials assigned it ends up being split across two models Untitled.zip - assigned a different material for one of the cushion on the bed. See what I mean by saying you should test your PR more thoroughly, we shouldn't be having this much back and forth.
Can you tell which mesh to look for in structure? And you mean if material has multiple materials its only applying first one?
There are two cushions on the bed, one of them is of the same material as the bed, while the other has a different one assigned to it, both of them are part of the bed model in the original fbx file. When imported as a split, the bed gets separated into two model asset, one for the bed and cushion of material A and another with only the other cushion with material B
Fixed material mapping mismatch between Stride and Assimp. Stride importer has one material per mesh, while Assimp exports multiple submeshes for multi-material meshes is what makes this tricky. Updated the mesh conversion logic to merge these correctly so materials now display correctly. @Eideren