Hi,
I’m currently trying bring an existing game level created in 3dsMax into Unity.
The game level uses lots of the same models e.g. the same tree is used many times in the scene. In 3dsMax the trees are all “instances” of each other.
However when I export to FBX and import into Unity, the FBX exporter seems to treat each tree as unique, hence I end up with really inefficient scenes in Unity.
I could write a Maxscript to delete all but one instance of each object from the 3dsMax scene, but I’d then have to rebuild most of the game level inside Unity.
Is there a better way ?
You could combine the meshes in Max into fewer groups of several trees. Try to keep the total poly count for each group around 5000 triangles. And try not to have any group be affected by more than one pixel light (if any) since that will increase rendering costs.If you need collisions with the trees, a mesh collider should work fine for each grouped object, but don’t mark them as convex, and I’m assuming you won’t need the trees to collide with each other
Today there is not great support for this scenario.
There’s some manual wrangling that you can do however. How much makes sense depends on your project. Here’s a few possible scenarios:
-
export just the tree to an fbx file, and place the trees in unity. Pro: Unity really likes to be used this way. Con: You can’t use max’s lightmapping features.
If you weren’t planning on using lightmapping anyway, I’d strongly suggest this approach.
-
Leave things like they are. Sounds silly, but could very well be the best approach.
-
add userdata to all these instances in max. something lile “thisisaninstanceof=myoriginaltree”
then write an asset postprocessor script (search your docs for postprocessgameobjectwithuserproperties)
that will scan all imported objects, and delete the ones that have this userdata on them, and replace them with a “unity instance” of the tree in question.
this way you could place them in max, and still recycle the same mesh over and over in unity.
It’s still a difficult process though, and things get more difficult when you start to get to lightmapping, since then you want your objects to be instances of the same mesh, but you do want them to have different lightmap uv sets.
Good luck.
Lucas
Hi Lucas, thanks for your excellent reply.
I think I now have a partial solution.
I’ve modified an existing Maxscript that iterates through all the objects in the Max scene, and then exports just one copy of each object that is instanced. It also writes an XML file that lists all objects in the 3dsMax scene with instance information. (See snippet at the bottom of this email).
So I need to read the Unity docs to see how to write a script that can parse the XML file and create instances of the models into the scene in Unity.
Thanks again
Roger Clark
e.g.
<?xml version="1.0"?>
<models>
<model filename="ADShell_01.FBX" name="ADShell_08">
<position x="-160.3" y="206.2" z="0.0"/>
<rotation x="0" y="0" z="90"/>
<scale x="1.0" y="1.0" z="1.0"/>
</model>
<model filename="ADShell_01.FBX" name="ADShell_05">
<position x="-120.3" y="60.0" z="0.0"/>
<rotation x="0" y="0" z="-90"/>
<scale x="1.0" y="1.0" z="1.0"/>
</model>
.
.
.
</models>
I’m not sure if this will help you, but I’ve been working with a workflow on some 3dsmax data… the 3d data I am supplied with contains objects that represent where trees should be placed within the scene. I’ve written a quick and dirty editor script that takes a prefab and instantiates it across all selected objects (in my case all of the tree placeholders)
// Tree Spawner
// Add menu named "Spawn Trees" to the main menu
@MenuItem ("GameObject/Spawn Trees")
static function SpawnTrees ()
{
Debug.Log ("spawn those crazy trees!");
var prefab : Transform = EditorUtility.FindAsset("3d Assets/treeFab.prefab",Transform);
for (var i = 0; i < Selection.transforms.length; i++)
{
var tempClone : Transform = EditorUtility.InstantiatePrefab (prefab);
tempClone.transform.position = Selection.transforms[i].position;
}
}
// Validate the menu item.
// The item will be disabled if no transform is selected.
@MenuItem ("GameObject/Spawn Trees", true)
static function ValidateSpawnTrees () {
return Selection.transforms != null;
}
So although its a bit hacky, it might be an option worth considering.
Joe,
Thanks for your code, I’ve been working on a similar solution all day!
I didn’t realise I could have written the utility in Javascript, so I’ve been struggling to write it in C# (which has taken me ages, as I’ve had to write the XML parser from scratch). I’m not a C# programmer, I’m more of a Javascript / Actionscript person!
Anyway, the utility reads my XML file, parses it, then instantiates the relevant models, then moves and rotates them as required by the XML file.
I’ve still got some problems with the script, as I can’t seem to set the localScale on the instantiated object
I also need to make the script set the Scale Factor on the fbx files, as they keep comming in at 0.01 regardless of setting in Max
Anyway, if I get it into a fit state I’ll post the script to the forum.
Thanks
Roger
Please note that you have pretty much full access to the entire .net class libraries. So just use System.XML for your xml parsing.
C#/javascript doesn’t really matter very much, they both have access to the same class libraries.
(btw, using System.XML to your runtime scripts actually grows your webplayer, but since this is for an editorscript that doesn’t matter)
Bye, Lucas