- 1 Overview
- 2 Performance considerations
- 3 Fixture blueprints
- 4 Modelling a fixture
- 4.1 Fixture Orientation
- 4.2 Fixture Y-Axis Thresholds
- 4.3 Deciding What Sub-Meshes You'll Need
- 4.4 Creating the Sub-Meshes
- 4.5 Additional Considerations
- 5 Fixture setup within Unreal Engine 4
- 6 Cooking and sharing your mod
- 7 Additional notes
- 8 See Also
A fixture is a collection of files, for which a
cpp file serves as the parent file. All the settings for a fixture are inside this
- A UV mesh is the silhouette of the cutout hole that a fixture makes in a car body.
- A conforming mesh (e.g. grilles, outer light glass, or body moulding) will deform to the shape of the body.
- A skinned mesh (e.g. light internals) will maintain its relative internal shapes, but will conform roughly to the shape of the body.
- An addditional mesh (e.g. mirrors) will retain its shape no matter where it is placed on the body.
The performance of fixtures (and bodies) in UE4 is a constant discussion of balance.
There is a performance impact to poly count with fixtures in that a ray is cast to the body for every vertex; the more vertices there are in a mesh, the longer it'll take to conform to the body. This is why you'll see more detailed fixtures sit there for a few seconds before conforming to the car.
This is doubly so for fixtures that cut into the body—a UV mesh's vertices are raycast to the car on every frame while you're dragging the fixture around. UV meshes impact performance significantly with a higher poly count; try to keep UV meshes as low-poly as possible.
For optimal performance:
- Keep UV meshes lower than 100 triangles. With between 100 and 150 triangles, the fixture may lag when being dragged around; any higher and it will lag too much to use properly.
- Try to keep conforming meshes lower than 5,000 triangles. Higher-resolution meshes take longer than usual to conform to the car once they are placed.
Meshes (more on these later):
- Conforming Mesh - Defines the Static Mesh sub-mesh used by this fixture.
- UV Mesh - Defines the UV Mesh sub-mesh used by this fixture.
- Skinned Mesh - Defines the Skinned Mesh sub-mesh used by this fixture.
- Additional Mesh - Defines the Additional Mesh sub-mesh used by this fixture.
- Text Data - Currently not used.
- GUID - Unique identifier for this fixture.
- Family GUID - Identifier for this fixture family. This should be unique to every other family GUID, and identical to every other variant of this fixture.
- Fixture Type - What category this fixture should be in (e.g. headlight, aerial, grille, etc).
- Centre Snap Distance - Defines at what distance, in cm, the fixture will snap to the centre line of the car (10 by default).
- Lock Normal to Cardinal- Determines whether the fixture will conform to one of the five cardinal directions in 3d space (forwards, backwards, left, right, or upwards) by default. A non-cardinal-locked fixture will simply face in the direction of the surface on which it is placed. Cardinal locking is useful for fixtures such as lights and mirrors, since it ensures that they don't face in (or conform to) odd directions.
- Export Breakability Override - Certain categories of fixtures can break off when damaged in BeamNG.drive. This setting lets you force a fixture to be breakable or unbreakable.
- Fixture Shape - Used to filter fixtures by rectangular, round, or complex shapes. Mostly used for lights.
- Year - Used to filter fixtures by year. Useful for era-specific fixtures, such as sealed beam headlights.
- Use This Fixture as Family Preview - if you have many variants of a fixture, enabling this setting for one variant will make it the one that shows up in the main fixture menu (overriding the first fixture as per alphabetical order).
- Fixture Class - Set this to
A_Fixtureto ensure that the fixture works as intended in-game.
The UV Mesh (imported as a Static Mesh in UE4) is a flat silhouette that tells the fixture to cut a hole into the car body. You will only need vertices along the outside edges of the UV mesh, and an UV mesh is only required if your fixture intends to cut into the car.
The Conforming Mesh (imported as a Static Mesh in UE4) is a mesh where each vertex is deformed to match the surface of the car body. It is also a required mesh if the fixture has a UV mesh, as the conforming mesh is used to cover the jagged edge of the hole created by the UV mesh. A conforming mesh that could logically be placed on top of other fixtures should also have its outside edges extend beneath the body; the default distance for this extrusion is slightly farther than 10 cm.
The Skinned Mesh (imported as a Skeletal Mesh in UE4) is used when you have parts of a fixture that should conform to the rough shape of the car, but also retain the dimensions and ratios of any individual components. A skinned mesh will have a bone for each element that is parented to a root bone.
All vertices of the skinned mesh that are within 1.5 mm of the car body surface will conform to the car as if they were part of a conforming mesh. Because of this, there may be a small gap of at least 1 mm between the edge of the skinned mesh and the car body. To cover up this gap, a conforming mesh is used to connect the edge of the skinned mesh with the car body.
The Additional Mesh (imported as a Static Mesh in UE4) does not deform in any way and will remain in place relative to the location of the fixture. An additional mesh has no skin or bones, and no part of it will deform to the shape of the car. Examples of additional meshes are exhaust tips and wing mirrors.
Note: This how-to assumes a general understanding of polygonal 3D modelling software. Any 3D modelling package will do, as no custom scripts are required to author fixture meshes.
Hard Rooster has created a full video series for fixture modding in Blender.
The full series can be found here.
Fixtures are oriented in the following manner in a 3D modelling program. Note how the negative Y axis faces forwards.
Fixture Y-Axis Thresholds
There are 2 important values to take in to note for fixture sub-meshes.
- A skinned mesh will have some of its vertices conform to the car as if it were a conforming mesh, but only if those vertices are within 1.5 mm from Y=0. A vertex with a Y axis value of 1.5 mm will conform to the car as if it were part of a conforming mesh, and a vertex with a Y axis value of 2.0 mm will not.
- The outer edges of most conforming meshes (and inner edges of things with holes in them, like open grilles) usually sit 10.114 cm below the surface (that's a Y-axis value of 10.114cm). This stops fixtures from appearing to 'float' when put on top of other fixtures that cut into cars and leave holes, such as grilles.
It's a bit confusing at first, but following these rules will ensure your fixture works correctly.
Deciding What Sub-Meshes You'll Need
Fixtures have a fairly convoluted list of things that are or are not needed, depending on what is in the fixture.
- If you have a UV mesh, you need a conforming mesh to cover the hole.
- If you have a conforming mesh, it isn't required to have anything else unless said Conforming Mesh has parts that go below the car body mesh (in which case you'll need a UV Mesh to cut a hole out for it).
- If you have a skinned mesh, you'll need a conforming mesh and a UV mesh, as a skinned mesh can only be inside the car. Therefore, a UV mesh is needed to cut out that hole, and a conforming mesh is needed to cover the edge of that hole.
- If you have an additional mesh positioned above the car body, nothing else is needed. If the additional mesh is obscured by the car body mesh, you'll need a UV mesh to cut out the hole for that (and by extension, a conforming mesh to line that hole).
For this example, we'll make the components for the headlight fixture below (a Conforming Mesh, UV Mesh, and a Skinned mesh with 4 bones).
Creating the Sub-Meshes
Creating a UV Mesh
The UV mesh defines the texels of the car body that will be cut out by the fixture. Each vertex is used as a point of reference, and lines are drawn between them along the edges of the UV mesh to define the final cutout shape. If there are too few vertices, the cutout shape will become distorted, since the vertices are projected onto the car texture before being cut out (with the actual edges of the UV mesh not being used), resulting in waviness between vertices in the cutout shape. This is more pronounced on larger fixtures, or fixtures that are stretched to several times their original size.
A UV mesh should have vertices at regular intervals around the outside to determine the cutout shape of the fixture. Any vertices that aren't on an edge are irrelevant and will only make the fixture slower to render. Note that UV meshes can be made in annulus shapes, like a doughnut.
The UV mesh should be roughly halfway between the outside edge of the skinned mesh (which should share its edge with the inside edge of the conforming mesh) and the outside edge of the conforming mesh.See below for the example UV mesh in comparison to its respective conforming mesh.
If you're having trouble with wavy cutouts on cars, segment your UV mesh into quads instead of a starburst pattern, as shown here.
Creating a Conforming Mesh
A conforming mesh is a single basic polygonal mesh that conforms to the shape of the car body.
The conforming mesh should have enough polygons at regular intervals so that it doesn't appear blocky or clip through the car body. The more polygons you add to the conforming mesh, the longer it will take to calculate its final morph position, but this does not impact performance when it is dragged around.
For this example fixture, we'll be using a conforming mesh for two purposes:
- Connecting the skinned mesh to the car body.
- Covering the cutout hole created by the UV mesh.
However, a conforming mesh can be used without a skinned mesh, such as:
- for trim pieces, bonnet bulges, or badges.
- for vents and grilles, when used with a UV mesh.
We'll start by using the UV mesh as our reference point. Our conforming mesh needs to cover the hole created here, so we'll make a ring of faces to surround the UV mesh with enough width to not allow any visible gaps between the cutout and the conforming mesh. We'll extend this edge out along the -Y axis (forward from the car body) by a millimetre or two to prevent faces from clipping through the car body, and we'll extrude a ring of faces around the outside of it to connect the mesh to the car body like so:Because this fixture is going to have a skinned mesh, we'll need to take that into consideration too. A skinned mesh will have any vertices that are farther than 1.5 mm in the -Y axis conform to the car in the same way as a conforming mesh, so we'll need to match this mesh structure such that the two meshes connect seamlessly.
Here is the conforming mesh, with the skinned mesh and UV mesh:This headlight fixture will also have a glass cover over it, so we'll add that in now. For this example, I've added a small step to the inside of the conforming mesh to add a little bit of detail. The glass cover will then be placed on top. You'll also notice that the outside edge of this headlight has been extruded deep behind the surface; this is so it can be placed on top of other headlights or grilles and not appear to float.
Unwrapping the Mesh
The next step is to unwrap the mesh. We'll be using 3ds Max's default UVW Map modifier, setting it to 'box' projection (cube projection in Blender), and setting the length, width, and height dimensions all to 2. This value is important if your fixture mod intends to use our default materials, because said materials assume that the UVs of the fixture conform to this setting.
Basically, what this is doing is UV mapping the mesh so that the 0-1 areas of the UV map are 2cm².We'll go over the import process and material setup after we've created all of the meshes.
Creating a Skinned Mesh
A skinned mesh is the most complicated mesh in a fixture. It follows the same rules as the conforming Mesh in terms of overall mesh structure and UV mapping, but the manner in which it conforms to the car is more nuanced.The vertices of a skinned Mesh will conform to the car in the same manner as the conforming mesh if those vertices are within 1.5 mm of the Y axis. This is useful for having these parts of the mesh connect to a conforming mesh, as they will conform the same in that area.The rest of the mesh will conform relative to their skinned bones and weights. For this example, I've created a Skinned Mesh with 4 bones, and weighted them like so:
Take note that the vertices that conform to the mesh do so in the same manner as the conforming mesh, but are still weighted to their respective bones. This is because Automation's fixture system uses the distance that these vertices were morphed to determine how far back to conform each bone. If these vertices were weighted to the root bone instead, the fixture would not know how far to morph the skinned sections of the mesh.Unreal Engine 4 also requires a bone hierarchy, so I've made a root bone and parented all of the other bones to it. The root bone should not be weighted to any vertices.
Unwrapping the Mesh
Assign the same box map (with a scale of 2, 2, 2) as you did with the conforming mesh.
Creating an Additional Mesh
An Additional Mesh is a simple mesh with no skin or morphs that does not deform in any way. The Additional Mesh does rotate around the fixture position, and will maintain its relative position from its pivot point.Take the following example: an exhaust fixture. Note that the entirety of the exhaust is offset from the pivot point—this is so that it can hang under the car, since the fixture itself must have its pivot point on the car.
Unwrapping reflector lights
If your fixture is a light that contains a reflector surface (such as an incandescent bulb), there are some special considerations.
Let's take a look at this fixture as an example:
Several things are of note with regards to light components:
- The bulbs themselves should be unwrapped as a single point with zero scale exactly at UV coordinate
0.5,0.5(the UV is scaled to a single point in the very center).
- The main reflector surface should be unwrapped such that each quad face fills the entirety of the
0-1UV coordinate space (
Reset UV projectionin Blender).
- The side walls of the reflector (and any other part of the reflector that you want to have vertical or horizontal lines on) should be unwrapped as a single point with zero scale exactly at UV coordinate
0,1(the UV is scaled to a single point in the bottom left corner).
- Parts of the reflector that should appear flat should be unwrapped as a single point with zero scale exactly at UV coordinate
0,0(the UV is scaled to a single point in the top left corner).
Applying materials to a light component
The bulb and reflector for each light should be assigned to the same material slot to save on draw calls. Each separate light, however, should be a different material slot for freedom of choice in terms of light configurations.
Unwrapping radial glass
For light glass with a radial pattern, unwrap the glass so that the radial pattern fills the whole UV space as a single texture.
This step assumes that the correct version of Unreal Engine is installed and configured correctly. See Modding for more information on the correct version of Unreal Engine to use and how to view mod content folders. Also see the official Unreal Engine documentation on importing FBX files for more information.
Creating your Fixture Mod Plugin
Using the correct version of Unreal Engine, with our modding tool project opened and plugins loaded, select 'Create Mod' from the top menu bar.
There are several ways to import your sub-meshes to this mod folder. The easiest is to simply navigate to the folder you want to import your files in the Content Browser, then click the 'Import' button to import files to that folder, select the meshes you want to import, and click 'Open'.
UV meshes, conforming meshes, and additional meshes should be imported as static meshes ('Skeletal Mesh' is un-ticked in the import dialogue), while skinned meshes should be imported as skeletal meshes ('Skeletal Mesh' is ticked in the import dialogue). Note that 'Skeletal Meshes' will import with additional 'Skeleton' and 'Physics Asset' files. These are important. You don't need to do anything with them, but don't delete them.Note that 'Import Materials' is also unticked, as we do not want to import any materials from the modelling software.
The final set of imported files in Unreal Engine should look like this:Once your files are imported, it's important to set 'CPU Access' to true for all static meshes. You can do this by selecting every static mesh, right-clicking on it and selecting 'Set Meshes to Allow CPU Access'.
Default Materials and Material Slots
The fixture material system in Automation relies on the name of the material slots within the meshes to define what materials can be applied to the fixture. Therefore, assigning the correct materials to the meshes is only important for the initial selection and loading of that fixture. In this manner, it is possible to have custom materials applied to your fixture with it still being compatible with Automation's fixture material menu.
The fixture material menu in Automation relies on the names of the material slots on the sub-meshes to decide what category of materials the player can select from, with said names in the format
category_# (case-sensitive, with '#' being a single- or multiple-digit number of choice).
With light fixtures, the names of the slots for the corresponding pair of glass and reflector material slot names should share the same number. For example, a fixture with two lights would have
glass_01 (or just
Assigning Default Materials
While the slot names define what materials the player can choose from in-game, it doesn't define what material first gets loaded when the fixture is spawned in.
When the fixture is first placed on the car, it loads the material that is set in that fixture's sub-mesh default materials. For the sub-mesh examples above, you can see that not only have the slots been named appropriately, they also have materials assigned to them. Therefore, for all your fixture sub-meshes, default materials should be applied. (They're not strictly necessary, but your fixtures deserve better than the default grey checkered material.)
To find where all the materials available in-game are, open up the
CarMaterialUtils blueprint (located in
Utility), and open the 'Get Materials from Slot' function. There, you can view the list of each material that gets assigned to each slot, find them in the content folder, and assign them to your mesh as the default material. Note, though, that these steps are only to find where the default materials are. We do not use the Utils blueprint itself to assign materials to fixtures.
To do this, open
...then open 'Get Fixture Materials from Slot', located in
Car Painting ->
From there, select the corresponding materials array for the material category you want to apply to your sub-mesh from the Local Variables tab, and in the details panel you'll see an array of the materials used for that slot type. By expanding that, you can see the materials, and by selecting the small magnifying glass icon, view that material in the Content Browser, and from there apply it to your sub-mesh.
Creating and Setting Up the CPP File
Right-click in the content browser, and from the 'Camso' sub-menu, select the 'Fixture Preview Data' option. You should now have a fixture CPP file in your content browser.Open the CPP file. You should get something like this:
Fill out the 'Meshes' section with the meshes you've made, leave the 'Text' data empty, generate a GUID and Family GUID (or copy the family GUID if you're making a variant), and set the 'Fixture' settings to the relevant info as laid out near the top of this page. Finally, in the 'Path' section, make sure there is one item in the array, and fill it with
A_Fixture. This is important; your fixture will not work if this is not filled correctly.
When you're done, you should have something that looks like this:Be sure to save your files.
Creating the ThumbnailYou should already be here by default when you load up the Automation project. Check the top tab in Unreal and make sure it says 'ThumbnailGeneratorLevel_Fixture'. If you are not in the thumbnail generator level, open it from
Generate Fixture Thumbnails
Select the Fixture Thumbnail Generator from the World Outliner, and add your fixture blueprint to the 'Fixture Previews to Generate' array (by first clicking the 'plus' icon, then putting the fixtures you have created into the list). Repeat this process for every fixture you have created. It does not matter if these fixtures are of the same family or not. Then, select 'Export Preview' to generate the Thumbnail file.
Because these files are created by the modding tools, they need to be manually saved (even if no asterisks are present).
Your fixture mod is now ready to be shared!
To use the mod you have just created, you need to 'share' it. See the main Modding page on how to share your mod.
- Fixtures should not have any vertices along the centre axes to avoid any miscalculation by the fixture gizmo. If the game casts a ray through the centre line of the car, it may miss the two halves of the car and return a false positive of the fixture being out of bounds. Offsetting your vertices slightly will avoid this. Additional meshes are the sole exception to this rule, as they do not conform in any way.
- If you're testing out a fixture and the meshes it uses haven't been finalized, you can use UE4's 'Reimport' function to replace the existing mesh with a newer version of it. All the materials already assigned to the mesh will be preserved, as will its reference in the blueprint, saving you the trouble of manually reimporting a mesh and having to reassign materials and put it into the blueprint again. This works for car body meshes as well.
- Is CPU access still turned on for all static meshes? If your mod causes a crash or isn't visible in-game, this might be unticked. It does that sometimes; re-enable it and try again.
- If the first fixture in a thumbnail generation array ends up with an unusually sparkly thumbnail, this can be fixed by giving it an additional duplicate array entry (which forces UE4 to render the thumbnail again normally).