Material effects expose the way a surface material reacts to other materials. For example, a metal material will react to bullet impacts differently (i.e. by generating sparks) than a grass material does (i.e. by generating dirt or dust).
Because hard-coding these effects in code would be impossible to keep updated, these effects are exposed through a small number of asset files.
- The SurfaceTypes, defined in
Game/Libs/MaterialEffects/SurfaceTypes.xmldefines the physical properties of all the available material types. It can be edited with any text editor.
- The MaterialEffects, which usually resides in
Game/Libs/MaterialEffects/MaterialEffects.xml, define the interaction of 2 materials, i.e. what effect to generate on an interactive event between 2 surface types. For example, it defines that when a bullet collides with the soil surface, a dirt particle effect is spawned. This file has to be read and edited with Microsoft Excel.
- The Effect libraries, found in
Game/Libs/MaterialEffects/FXLibs, contain the associated effects. The ammo files in
Game/Scripts/Entities/Items/Ammodefine what material a bullet is made from.
Creating a New Surface Type
Adding a Surface type to SurfaceTypes.xml
A surface type is defined by the XML element SurfaceType. Its attribute name is the one that can be selected in the Sandbox Editor.
Surface types defined here will appear as options in the drop down list of the Material Editor. The other attribute type is optional. It can be used in other processes by game code. The physical parameters are defined by the Physics element.
A material's friction (friction is the average of contacting materials). A recommended default is 0.8. Internally it's clamped to 0.1 if it's below that.
Also known as Bounciness. It's averaged from 2 materials. Clamped to 0 as the elasticity can't be negative. Recommended default is 0, unless you specifically want something bouncy.
Procedural breakability index; a corresponding boolean cutter shape should be registered in the physics.lua.
Integer from 0-15, with 0 being the least pierceable. For each ray, a hit is pierceable if ray's pierceability is less than the material's pierceability.
Energy= (mass*velocity^2/2) and it refers to the colliding object that triggers breaking (typically should be tweaked based on bullets' params).
Each collision above break_energy takes round_to_int(collision_energy/break_energy) hitpoints; real breaking only happens when hitpoints are depleted.
Max amount of hitpoints a single hit can take.
Hitpoints can be localized with this radius (i.e. it'll require that all hits are within this radius from each other); 0 disables.
Lifetime for localized hits info, it expires after that (note that it's just a hint; it can expire earlier if there are too many newer hit infos, or later if there's no concurrency).
Characteristic size for boolean carving; shape registered in physics.lua is scaled by this size / shape's characteristic size (specified in physics.lua).
Same as above, but for explosions (first one is for collisions with bullets and general physicalized objects).
If set, uses 2D breakability instead of 3D boolean carving.
Entire node will only collide with vehicle (even if material with this flag is only applied to some triangles of it).
The breakable parameters are defined by the breakable_2d element.
Procedural hole size (note that when an object hits the surface, it will use the colliding area's size instead – unless it's smaller than this).
Same as above, but for the first hit that breaks the object.
Vertical hole size = blast_radius * (1+random(0..vert_size_spread)).
Broken pieces will be physicalized as rigid bodies (otherwise as physical particles).
Pieces will expire after that (currently it'll only happen when the player looks away, but that might change).
Cell size for the breakage grid (default 0.1).
Governs the number of grid triangles in each shard (triangles are taken from the breakage grid, around the hit point and within blast_radius); default is 6.
Filters the hole's edges with this angle to avoid the 'saw tooth' look; default 0 (disabled), but 75 seems to look good in most cases.
Used to calculate shards' masses and buoyancy (float/sink) properties; default 1200.
Triggers full fracture when the object is damaged beyond this (0..1); default 1.
Name of the effect to generate along the broken edges.
Single effect for each breakage.
Effect to play when a full fracture condition is triggered.
In case of full fracture, doesn't generate broken pieces procedurally, relies only on full_fracture_fx.
Sets alpha of vertices along the broken edges to 0 (should be used if there's a special shader that expects that).
Puts a decal with this material whenever a break occurs.
Sets the decal size wrt the hole size (0 disables crack decals).
Besides the <Physics> element, the optional <BreakageParticles> defines the type of particle that will be spawned on breakage. Its attribute type defines the break event and can take one of the following values:
The effect attribute points to the particle effect that will be spawned on breakage, along with the attributes count_per_unit, count_scale and scale defining respectively the number of particle systems to be spawned, and their scale. Normally, their value should be 1.
Ammo surface types do not need to be added to the SurfaceTypes.xml file.
Adding Events to MaterialEffects.xml
New surface types have to be added both as a row and as a column, and have to be kept in the same order. The cross reference between 2 surface types defines the type of event that will happen on interaction.
Surface types that are only called by code are required to only have rows and must be added at the bottom, below the surface types defined in SurfaceTypes.xml (the exception is when it is needed to be used on materials through the Material Editor).
It should be noted that Objects which need to use Alpha Test for Collision (railings, etc) should have a surface type with the suffix _RayProxy. This is also used to allow characters to see through glass objects and such as part of the perception system.
Adding Material Effect Events
Material effect (MFX) events are those events that occur at interactions between 2 surface types, as defined in MaterialEffects.xml. They are named according to the following schema:
For instance, bulletimpacts:hit_mat_soil points to the event (and XML element) hit_mat_soil defined in
This event is defined as follows:
Each effect Name can have the following optional additional attributes:
Effect spawn direction:
minscale / maxscale
Scale to apply to effect when it's near / far from camera.
Distance at which maxscale applies.
Max distance to show effect.
Adding an Ammo Surface Type
The surface type for ammunition is the attribute name of the XML element ammo in an ammo file. Its value is required to be the same as the value in the MFX table.
There exist a couple of console variables to debug the Material Effects in the Sandbox Editor or the Launcher:
mfx_Debug: 0 (Disabled) / 1 (Collisions) / 2 (Breakage) / 3 (Both)
- mfx_DebugVisual: 0 (Disabled) / 1 (Basic visual debugging) / 2 (Enhanced visual debugging):
- mfx_DebugVisualFilter: 0 (Disabled) / Name (Only show visual debug information for this Material Effect).
- mfx_DebugFlowGraphFX: 0 (Disabled) / 1 (Show debug information for triggered Material Effect flowgraphs)
Non visual debug information will be shown in the console.
To reload all Material Effects from the MaterialEffect.xml file it is possible to use the console command mfx_reload.
Because it is necessary to have matching rows and columns in the MaterialEffects.xml file it is possible to set mfx_debug to 1/2/3 for an automatic check before reloading the Material Effects. Any warnings are outputted to the console.
The MFX table is prone to breakage and unexpected behavior when the order in rows and columns is different from the expected one, e.g. after using find-replace and/or inserting cells.