POLYMASON

How to import an OBJ into Unity

Part of The OBJ file format, explained for game engines

Unity imports an OBJ the moment it lands in the Assets folder. Most of the time that is all there is to it. This is the step by step, and the three things that go wrong: size, colour and shading. What an OBJ carries and what it leaves to the importer is in the OBJ guide; the same steps for Godot and Unreal sit beside this one, and if the format itself is still open, OBJ, FBX, GLB or STL settles it.

The import

  1. Put the .obj, its .mtl and any texture it names in the same folder, and drag the folder, or the files together, into the Project window. Unity imports the OBJ as a model asset with a mesh per object and a material per usemtl.
  2. Drag the model asset into the Scene or Hierarchy. It arrives as a GameObject with a child per object in the file, each with a Mesh Filter and a Mesh Renderer.
  3. Look at it. If it is the right size, in colour, and shaded the way you expect, you are done.

The wrong size

An OBJ has no unit; Unity reads its numbers as metres. A model made in metres arrives right. A model made in centimetres arrives a hundred times too big; one made in a tool that exported in millimetres, a thousand times.

Fix it on the model asset, not the GameObject. Select the .obj, open the Model tab, and set Scale Factor: 0.01 for a file in centimetres, 0.001 for millimetres. Press Apply. Scaling the GameObject instead works too, but the scale then travels with the object, scales its children and colliders, and confuses anything that reads its transform.

The Convert Units checkbox below it applies only to files that state a unit, which FBX does and OBJ does not. For an OBJ it does nothing.

The famous case, a Blender model arriving a hundred times too big, is an FBX problem: Blender's FBX exporter writes centimetres by default and Unity's importer reads them, and the fix is Convert Units or a scale of 0.01. Blender's OBJ exporter writes metres and needs nothing.

The wrong way up

Unity is Y-up; the OBJ says nothing about which way is up. A model exported from a Z-up tool with the wrong settings arrives on its side. Re-export with the exporter's forward and up options set for Y up; in Blender's OBJ exporter that is Forward -Z, Up Y, which is the default. If you cannot re-export, rotate the GameObject by -90 on X and make it a child of an empty so the rotation is hidden from the rest of the scene.

Grey where it should be coloured

The .mtl was not next to the .obj when Unity imported it, or the texture it names was missing. Put them together and reimport: right-click the model, Reimport. Unity makes a material per newmtl and looks for map_Kd textures by file name in the same folder and its subfolders.

The Materials tab controls this. Material Creation Mode should be Standard (or Import via MaterialDescription in recent versions); None gives you a grey default material for everything. Location decides whether the materials live inside the model asset, Use Embedded Materials, or as separate assets; Extract Materials writes them out so you can edit them, which you will want to for a palette-textured model to set smoothness to zero.

Smooth where it should be flat

The trunk looks like a tube, the foliage like a balloon. The file has no normals and Unity calculated smooth ones, or the file has smooth normals. On the Model tab, set Normals to Calculate and Smoothing Angle to 0, and Apply. The flat shading guide is the whole of this problem and the smoothing angle article is that one setting; the short version is that a file with flat normals in it needs nothing, and one without needs the angle set.

Colliders

The importer's Generate Colliders checkbox on the Model tab adds a Mesh Collider to every mesh. For a prop, fine. For a tree, wrong: a mesh collider on foliage stops the player walking under the canopy. Leave it off and add a Capsule Collider on the trunk by hand, or in a prefab. The tree colliders article covers it.

Read/Write and other settings

Read/Write keeps a copy of the mesh in memory for scripts to read; off by default and leave it off unless you modify meshes at runtime, since it doubles the memory. Mesh Compression trades precision for size; Off for anything you might scale up. Optimize Mesh reorders triangles for the GPU; leave it on. Import BlendShapes, Import Visibility, Import Cameras and Import Lights do nothing for an OBJ.

Making it a prefab

Drag the configured GameObject from the Hierarchy back into the Project window to make a prefab, with its colliders and any LOD Group. Instances of the prefab in scenes update when the prefab changes, and reimporting the model updates the mesh without touching the prefab's settings.

What PolyMason's files need

Nothing. The tree builder writes metres, Y up, the model standing on the ground at the origin, flat normals in the file, and one material whose texture is a palette PNG in the same zip. Drop the zip's contents into a folder and the importer's defaults do the rest.

More in this guide

Or build a tree and see what comes out.