Python
LOD Tailor’s editor subsystem, TALODTailorSubsystem, gives Blueprint and Python access to the same scans, verdicts, batch runs, backups, reports and settings as the panel.
Get the subsystem
Section titled “Get the subsystem”import unreal
tailor = unreal.get_editor_subsystem(unreal.TALODTailorSubsystem)In Blueprint (for example in an Editor Utility Widget), get the LOD Tailor editor subsystem (class TALODTailorSubsystem) and use the functions in the ta LOD Tailor category.
Functions
Section titled “Functions”| Function | Returns |
|---|---|
scan_paths(paths, show_progress=True) |
TALODTailorReport |
scan_project(show_progress=True) |
TALODTailorReport |
scan_assets(assets, show_progress=True) |
TALODTailorReport |
describe_mesh(mesh) |
TALODTailorMesh |
audit_mesh(mesh) |
Array of TALODTailorIssue |
advise_nanite(mesh) |
TALODTailorNaniteAdvice |
get_targets() |
Array of TALODTailorProfile |
get_presets() |
Array of TALODTailorPreset |
get_presets_for(kind) |
Array of TALODTailorPreset |
get_folder_rules() |
Array of TALODTailorFolderRule |
make_apply_options(preset_name) |
TALODTailorApplyOptions |
make_apply_options_for(preset_name, skeletal_preset_name) |
TALODTailorApplyOptions |
plan(report, meshes, options) |
TALODTailorPlan |
apply(plan, show_progress=True) |
TALODTailorApplyResult |
restore_backup(backup_file, show_progress=True) |
TALODTailorApplyResult |
get_latest_backup() |
str |
get_default_export_options() |
TALODTailorExportOptions |
export_report(report, options) |
TALODTailorExportResult |
export_plan(plan, options) |
TALODTailorExportResult |
can_render_lod_pictures() |
bool |
save_lod_pictures(mesh, folder, size=160) |
Array of str |
get_settings_asset() |
TALODTailorConfig or None |
use_settings_asset(asset) |
Nothing |
create_settings_asset(asset_path, use_for_project=True) |
TALODTailorConfig |
export_settings(file_path) |
bool |
import_settings(file_path) |
bool |
apply_pending_import_rules() |
int |
snapshot_imported_lods(mesh) |
int |
find_lost_imported_lods(mesh) |
Array of int |
restore_imported_lods(mesh) |
int |
reimport_keeping_imported_lods(mesh) |
bool |
get_log() |
Array of TALODTailorLogEntry |
clear_log() |
Nothing |
distance_to_screen_size(target, bounds_radius, meters) |
float (static) |
screen_size_to_distance(target, bounds_radius, screen_size) |
float (static) |
open_panel() |
Nothing |
open_panel_with_paths(paths) |
Nothing |
open_panel_with_assets(assets) |
Nothing |
show_step_in_panel(step) |
Nothing |
select_in_panel(mesh) |
Nothing |
focus_target_in_panel(target_name) |
Nothing |
preview_in_panel(options) |
Nothing |
scan_paths, scan_project and scan_assets
Section titled “scan_paths, scan_project and scan_assets”Read and check static and skeletal meshes and return a report with every mesh, every finding and the Nanite or LODs verdicts, like a scan in the panel.
scan_pathsscans content folders such as"/Game/Props"and their subfolders.scan_projectscans the Included Paths from the settings.scan_assetsscans a list ofunreal.AssetData, for example the Content Browser selection. Assets other than static and skeletal meshes are ignored.
All three skip the Excluded Paths. With show_progress=True a progress dialog with a Cancel button is shown; cancelling returns the meshes read so far. Pass False in scripts that run unattended.
These functions don’t wait for the Asset Registry. Right after the editor starts, wait until asset discovery has finished, or some meshes will be missing. (An editor started with -ExecutePythonScript waits for discovery before it runs the script.)
describe_mesh, audit_mesh and advise_nanite
Section titled “describe_mesh, audit_mesh and advise_nanite”describe_mesh reads one loaded unreal.StaticMesh or unreal.SkeletalMesh: its LODs, triangles, sections, screen sizes, Min LOD, Nanite state and, for skeletal meshes, its bones. audit_mesh returns the findings of one mesh on the enabled targets, the same findings Data Validation reports (before Min Validation Severity is applied). advise_nanite returns its Nanite or LODs verdict for every enabled target.
get_targets, get_presets, get_presets_for and get_folder_rules
Section titled “get_targets, get_presets, get_presets_for and get_folder_rules”get_targets returns the enabled targets, get_presets all LOD presets and get_folder_rules all folder rules, from the settings asset when the project uses one and from Project Settings otherwise. get_presets_for(kind) returns the presets offered for unreal.TALODTailorMeshKind.STATIC_MESH or SKELETAL_MESH (for skeletal meshes, your skeletal presets followed by the two built-in ones, unless one of your presets has the same name). Changing the returned copies doesn’t change the settings.
make_apply_options and make_apply_options_for
Section titled “make_apply_options and make_apply_options_for”Return batch options with the default values and copies of the presets, found by name (case-insensitive). make_apply_options_for takes one preset for static meshes and one for skeletal meshes. make_apply_options takes one preset: a preset meant for static meshes sets the static recipe, one meant for skeletal meshes the skeletal recipe, and one meant for any mesh sets both. A recipe whose preset is not found starts with the first preset for its kind of mesh (Standard and Characters by default). Change the options before passing them to plan; the settings don’t change.
plan, apply and restore_backup
Section titled “plan, apply and restore_backup”plan is the dry run behind Preview changes: it returns what a batch run with these options would do to each mesh of the report, without changing anything. meshes is a list of unreal.SoftObjectPath of the report’s meshes to include; an empty list includes every mesh of the report. With use_folder_rules on, meshes that match a folder rule get its preset.
apply executes a plan like Apply in the panel: it writes a backup first, then changes, builds and (with save) saves the meshes. Entries with the action SKIP are not touched and count as skipped. It asks for no confirmation. With show_progress=True a progress dialog with a Cancel button is shown. The run is added to the panel’s Log.
restore_backup puts back the settings of a backup file. Pass the full path of any backup, restored or not, or an empty string for the newest one that hasn’t been restored. Like the panel, a complete restore renames the file to Restored_LODTailor_<time>.json. See Restore for what a restore can and can’t put back.
get_latest_backup returns the full path of the newest backup file in the Backup Directory that hasn’t been restored yet, or an empty string.
get_default_export_options, export_report and export_plan
Section titled “get_default_export_options, export_report and export_plan”get_default_export_options returns the report options from the settings: the Report Directory, all three formats and the LOD picture settings. export_report writes the report of a scan, export_plan the preview of a plan (lod_plan.html, .csv and .json, like Export preview). Neither opens the result in a browser.
If no format is selected, export_report writes nothing and errors contains “No format selected.”
can_render_lod_pictures and save_lod_pictures
Section titled “can_render_lod_pictures and save_lod_pictures”save_lod_pictures(mesh, folder, size=160) renders every LOD of a static or skeletal mesh from the same camera into JPEG files <mesh name>_<hash>_LOD<n>.jpg and returns their paths in LOD order. A relative folder starts at the project folder; the size is limited to 32 to 1024 pixels. can_render_lod_pictures() is False when the editor has no graphics device, as in a commandlet without -AllowCommandletRendering or with -NullRHI. In a commandlet, only static meshes are pictured. See LOD pictures.
Settings asset functions
Section titled “Settings asset functions”| Function | What it does |
|---|---|
get_settings_asset() |
The settings asset the project uses, or None when it uses Project Settings. |
use_settings_asset(asset) |
Uses this asset for the project (None: Project Settings again). Written to Config/DefaultEditor.ini. |
create_settings_asset(asset_path, use_for_project=True) |
Creates and saves a settings asset, for example /Game/Settings/DA_LODTailor, as a copy of the settings in use, and uses it for the project unless use_for_project is False. Returns None for an invalid path. |
export_settings(file_path) |
Writes the targets, presets, folder rules and reference camera in use to a JSON file. |
import_settings(file_path) |
Reads such a file into the settings asset in use, or into Project Settings. False for a file that is not a ta LOD Tailor settings file. |
apply_pending_import_rules() |
Applies the folder rules that apply on import to the new meshes imported since the last editor tick, and returns how many meshes changed. For scripts that import in a loop. |
See Shared settings and folder rules.
Reimport functions
Section titled “Reimport functions”| Function | What it does |
|---|---|
snapshot_imported_lods(mesh) |
Copies the imported LODs of a static or skeletal mesh before a reimport you run yourself. Returns how many it copied. |
find_lost_imported_lods(mesh) |
The imported LODs of the last copy that the mesh has lost since, by LOD index. |
restore_imported_lods(mesh) |
Puts the lost LODs back from the copy, as one undo step. Returns how many came back. |
reimport_keeping_imported_lods(mesh) |
Reimports the mesh from its source file without asking and puts back the imported LODs the reimport removed, whatever Protect Imported LODs on Reimport says. Returns True if the reimport ran. |
See Reimport protection.
get_log and clear_log
Section titled “get_log and clear_log”get_log returns the entries of the panel’s Log, oldest first: batch runs, restores, reimport protection, folder rules applied on import and settings changes of this editor session. clear_log empties it.
distance_to_screen_size and screen_size_to_distance
Section titled “distance_to_screen_size and screen_size_to_distance”Convert between a distance in metres and a screen size for a mesh with a bounds radius in centimetres, on a target’s camera (its field of view and aspect ratio). They don’t apply the target’s distance scale. See Distances and screen sizes for the formula. Both are static functions, so you can call them on the class.
Panel functions
Section titled “Panel functions”| Function | What it does |
|---|---|
open_panel() |
Opens the panel without scanning. |
open_panel_with_paths(paths) |
Opens the panel and scans these content folders. |
open_panel_with_assets(assets) |
Opens the panel and scans these assets. |
show_step_in_panel(step) |
Shows step 1 (Meshes), 2 (Findings) or 3 (Batch LODs). |
select_in_panel(mesh) |
Selects a scanned mesh (an unreal.SoftObjectPath) on the Meshes page. |
focus_target_in_panel(target_name) |
Selects a target chip by name. An empty or unknown name selects All targets. |
preview_in_panel(options) |
Opens Batch LODs with these options and previews them for every mesh the panel has scanned. |
When the panel is still waiting for the Asset Registry before it scans, show_step_in_panel, select_in_panel, focus_target_in_panel and preview_in_panel run after that scan.
The report types are read-only. Targets, presets, LOD steps, folder rules, batch options and export options can be changed. Enum values are written in capitals in Python, for example unreal.TALODTailorNaniteMode.KEEP_NANITE or unreal.TALODTailorMeshKind.SKELETAL_MESH.
TALODTailorReport
Section titled “TALODTailorReport”| Property | Type | Meaning |
|---|---|---|
meshes |
Array of TALODTailorMesh |
Every scanned mesh, sorted by package path |
issues |
Array of TALODTailorIssue |
Every finding |
nanite_advice |
Array of TALODTailorNaniteAdvice |
The Nanite or LODs verdicts, one per mesh, in the order of meshes |
profiles |
Array of TALODTailorProfile |
The targets that were enabled during the scan |
scope |
Array of str |
The scanned folders, or the names of the scanned meshes |
seconds |
float |
Duration of the scan |
time |
DateTime |
When the scan started |
TALODTailorMesh
Section titled “TALODTailorMesh”| Property | Type | Meaning |
|---|---|---|
object_path |
SoftObjectPath |
Object path |
name, package |
str |
Name and package path |
kind |
TALODTailorMeshKind |
STATIC_MESH or SKELETAL_MESH |
bones, unskinned_bones |
int |
Skeletal meshes: bones of the skeleton, and bones no vertex is skinned to |
lod_settings_asset |
str |
Skeletal meshes: the LOD Settings asset that drives the LODs, or empty |
lods |
Array of TALODTailorLOD |
The rendered LODs. For static Nanite meshes LOD 0 is the fallback mesh. |
nanite |
bool |
Nanite is on |
source_triangles |
int |
Triangles of the full mesh: the Nanite mesh, or LOD 0 before its own reduction |
bounds_radius |
float |
Radius of the bounding sphere at scale 1, in cm |
bounds_size |
Vector |
Size of the bounding box at scale 1, in cm |
lod_group |
Name |
LOD group |
auto_screen_size |
bool |
Unreal computes the screen sizes |
min_lod |
int |
Default Min LOD |
platform_min_lod |
Map of Name to int |
Per-platform Min LOD overrides |
materials |
int |
Number of material slots |
nanite_bytes |
int |
Size of the Nanite data on disk, in bytes; 0 without Nanite |
nanite_fallback_percent |
float |
Static Nanite meshes: the fallback mesh’s share of the triangles when it is set as a share, otherwise -1.0 |
translucent_material, masked_material, world_position_offset |
bool |
A material is translucent, is masked, or uses World Position Offset |
TALODTailorLOD
Section titled “TALODTailorLOD”| Property | Type | Meaning |
|---|---|---|
triangles, vertices |
int |
Triangles and vertices |
screen_size |
float |
Default screen size |
platform_screen_sizes |
Map of Name to float |
Per-platform screen size overrides |
percent_triangles |
float |
Share of triangles the reduction keeps; 1.0 when not reduced |
custom |
bool |
Hand-made (imported) LOD |
sections |
int |
Number of material sections |
merged_sections |
bool |
LOD Tailor merged the sections of this LOD (fewer draw calls) |
section_triangles, section_materials |
Array of int |
Triangles and material slot of each section |
section_material_groups |
Array of int |
Static meshes: for each section, the first section drawn with the same material and settings |
bones |
int |
Skeletal meshes: bones the LOD needs |
max_bone_influences |
int |
Skeletal meshes: the most bones that move one vertex, 0 when not known |
reduces_from_lod0 |
bool |
The LOD is a reduction of LOD 0 to a share of its triangles, the way LOD Tailor builds LODs |
reduction_bone_influences |
int |
Skeletal meshes: the bone influence limit of the reduction |
removed_bones |
int |
Skeletal meshes: bones the reduction removes from this LOD |
bytes |
int |
Estimated GPU memory of the LOD’s vertex and index buffers |
TALODTailorIssue
Section titled “TALODTailorIssue”| Property | Type | Meaning |
|---|---|---|
rule_id |
Name |
Rule id, for example OverBudget. See Checks. |
severity |
TALODTailorSeverity |
INFO, WARNING or ERROR |
asset_path |
SoftObjectPath |
The mesh |
message |
Text |
The finding |
targets |
Array of str |
The targets it applies to; empty for every target |
TALODTailorNaniteAdvice and TALODTailorNaniteTarget
Section titled “TALODTailorNaniteAdvice and TALODTailorNaniteTarget”| Property | Type | Meaning |
|---|---|---|
asset_path, name, kind |
SoftObjectPath, str, TALODTailorMeshKind |
The mesh |
nanite |
bool |
Nanite is on for the mesh now |
verdict |
TALODTailorNaniteVerdict |
Over all targets: KEEP_NANITE, NANITE_WITH_FALLBACK_LODS, SWITCH_TO_LODS, KEEP_LODS or CONSIDER_NANITE |
reason |
Text |
Why, in one sentence |
source_triangles, fallback_triangles |
int |
Triangles of the full mesh, and of the fallback mesh of a static Nanite mesh |
nanite_bytes, nanite_bytes_estimated |
int, bool |
Nanite data in bytes, and whether it is an estimate |
lod_bytes, lod_bytes_estimated |
int, bool |
Memory of a LOD chain in bytes, and whether it is an estimate |
material_risk, material_risk_text |
TALODTailorMaterialRisk, Text |
NONE, POSSIBLE or CONFIRMED, and what it is about |
notes |
Array of str |
Material notes: translucent, masked, World Position Offset |
targets |
Array of TALODTailorNaniteTarget |
One per target: target (name), verdict, reason, renders_nanite (the target draws the mesh with Nanite today), triangles (what it draws without Nanite) and budget |
TALODTailorProfile
Section titled “TALODTailorProfile”A target. See Target settings for the meaning and ranges.
| Property | Type |
|---|---|
name |
str |
enabled |
bool |
device |
TALODTailorDevice: DESKTOP, HANDHELD, CONSOLE, HEADSET or MOBILE |
platform |
Name (None without a key) |
nanite |
bool |
max_triangles |
int |
require_lods_above |
int (Require LODs Above) |
max_skeletal_triangles |
int |
require_skeletal_lods_above |
int (Require Skeletal LODs Above) |
distance_scale |
float |
field_of_view |
float |
aspect_ratio |
float |
min_lod |
int (-1: first LOD within the budget) |
TALODTailorPreset and TALODTailorLODStep
Section titled “TALODTailorPreset and TALODTailorLODStep”| Type | Properties |
|---|---|
TALODTailorPreset |
name, description, use (TALODTailorPresetUse: ANY, STATIC_MESHES or SKELETAL_MESHES), lods (array of TALODTailorLODStep, LOD 1 and up), auto_screen_size (let Unreal compute screen sizes, static meshes only) |
TALODTailorLODStep |
percent_triangles (share of the full mesh, 0.005 to 1.0; 0.5 = half), distance (metres on the reference camera, at least 0.1), max_bone_influences (skeletal meshes, 0 to 12, 0 keeps the mesh’s setting) |
TALODTailorFolderRule
Section titled “TALODTailorFolderRule”| Property | Type | Meaning |
|---|---|---|
enabled |
bool |
Rules that are off are ignored |
path |
str |
A content folder, or a wildcard on the mesh path such as /Game/Env*Rock* |
meshes |
TALODTailorPresetUse |
ANY, STATIC_MESHES or SKELETAL_MESHES |
preset |
str |
Name of the preset for matching meshes |
set_nanite_mode, nanite_mode |
bool, TALODTailorNaniteMode |
Use the rule’s own Nanite mode |
apply_on_import |
bool |
Apply the preset when a matching new mesh is imported |
TALODTailorApplyOptions
Section titled “TALODTailorApplyOptions”| Property | Type | Default | Panel option |
|---|---|---|---|
preset |
TALODTailorPreset |
The static recipe (also used for skeletal meshes while skeletal_preset has no LODs) |
|
skeletal_preset |
TALODTailorPreset |
The skeletal recipe | |
include_static_meshes |
bool |
True |
Change static meshes |
include_skeletal_meshes |
bool |
True |
Change skeletal meshes |
use_folder_rules |
bool |
True |
Use the folder rules |
generate_lods |
bool |
True |
Build the LOD chain |
replace_custom_lods |
bool |
False |
Replace imported LODs |
set_screen_sizes |
bool |
True |
Screen sizes from the distances |
platform_screen_sizes |
bool |
True |
Per-platform screen sizes (only with set_screen_sizes) |
platform_min_lod |
bool |
True |
Per-platform Min LOD |
save |
bool |
True |
Save the changed meshes |
reduce_draw_calls |
bool |
False |
Fewer draw calls from LOD |
draw_calls_from_lod |
int |
2 |
Its LOD, 1 to 7 |
merge_same_material_sections |
bool |
True |
Merge sections with the same material |
drop_sections_below |
float |
0.02 |
Drop sections under, as a fraction, 0 to 0.25 |
merge_into_main_material |
bool |
False |
Main material only |
remove_unskinned_bones |
bool |
False |
Remove unskinned bones from LOD |
remove_bones_from_lod |
int |
2 |
Its LOD, 1 to 7 |
min_triangles |
int |
500 |
Skip meshes under |
nanite_mode |
TALODTailorNaniteMode |
SKIP |
Nanite meshes: SKIP, KEEP_NANITE or DISABLE_NANITE |
nanite_fallback_percent |
float |
1.0 |
Fallback, 0.01 to 1.0 |
TALODTailorPlan and TALODTailorPlanEntry
Section titled “TALODTailorPlan and TALODTailorPlanEntry”TALODTailorPlan has options (the batch options), profiles (the enabled targets) and entries, one TALODTailorPlanEntry per mesh:
| Property | Type | Meaning |
|---|---|---|
asset_path, name, kind |
SoftObjectPath, str, TALODTailorMeshKind |
The mesh |
preset, recipe |
str, TALODTailorPreset |
The name of the preset the entry uses, and the preset itself |
folder_rule |
str |
The folder rule that picked the preset, or empty |
action |
TALODTailorPlanAction |
GENERATE (new LOD chain), UPDATE_SETTINGS (settings only) or SKIP |
note |
Text |
Why the mesh is skipped, or notes on the change, as in the preview’s Note column |
old_lods, new_lods |
int |
LOD count before and after |
triangles |
Array of int |
Expected triangles per LOD after the run |
screen_sizes |
Array of float |
Default screen size per LOD after the run; empty when no screen sizes are written |
min_lod |
Map of Name to int |
Per-platform Min LOD after the run, by platform key |
nanite_before, nanite_after |
bool |
Nanite before and after |
replaces_custom_lods |
bool |
The mesh loses imported LODs |
removes_bones |
int |
Skeletal meshes: unskinned bones removed from the far LODs |
bone_influences |
Array of int |
Skeletal meshes: the bone influences per LOD after the run (0 = unchanged) |
sections_before, sections_after |
Array of int |
Draw calls (material sections) per LOD before and after the run |
reduces_draw_calls |
bool |
Far LODs get fewer sections |
The per-platform screen sizes of a plan are not available from Python or Blueprint.
TALODTailorApplyResult
Section titled “TALODTailorApplyResult”Returned by apply and restore_backup.
| Property | Type | Meaning |
|---|---|---|
success |
bool |
True if no mesh failed |
changed, skipped, failed |
int |
Number of meshes |
backup_file |
str |
Full path of the backup that was written or restored |
errors |
Array of str |
Problems, for example a mesh that could not be loaded, or imported LODs a restore couldn’t bring back |
seconds |
float |
Duration |
TALODTailorExportOptions and TALODTailorExportResult
Section titled “TALODTailorExportOptions and TALODTailorExportResult”| Type | Properties |
|---|---|
TALODTailorExportOptions |
output_directory (relative paths start at the project folder; default Saved/LODTailor/Reports), html, csv, json (all True), lod_pictures (LOD pictures in the HTML report, True), max_picture_meshes (50, 0 to 1000), picture_size (pixels, 160, 64 to 512) |
TALODTailorExportResult |
success, output_directory (full path), main_file (the HTML file, or the first file written), files, errors, lod_pictures (number of LOD pictures in the HTML report) |
TALODTailorLogEntry and TALODTailorConfig
Section titled “TALODTailorLogEntry and TALODTailorConfig”| Type | Properties |
|---|---|
TALODTailorLogEntry |
time (DateTime), severity (TALODTailorSeverity), asset_path (the mesh, if any), message |
TALODTailorConfig |
The settings asset: profiles, reference_field_of_view, reference_aspect_ratio, presets and folder_rules |
Examples
Section titled “Examples”Scan and list the findings
Section titled “Scan and list the findings”import unreal
tailor = unreal.get_editor_subsystem(unreal.TALODTailorSubsystem)
report = tailor.scan_paths(["/Game/Props"], False)for mesh in report.meshes: print(mesh.name, mesh.kind, [lod.triangles for lod in mesh.lods], "Nanite" if mesh.nanite else "")for issue in report.issues: print(issue.severity, issue.rule_id, issue.asset_path.export_text(), issue.message, list(issue.targets))Use the Content Browser selection
Section titled “Use the Content Browser selection”selected = unreal.EditorUtilityLibrary.get_selected_asset_data()report = tailor.scan_assets(selected)Readiness per target
Section titled “Readiness per target”def ready_percent(report, target=""): if not report.meshes: return 0 flagged = {i.asset_path.export_text() for i in report.issues if i.severity != unreal.TALODTailorSeverity.INFO and (not target or not i.targets or target in i.targets)} return round(100 * (len(report.meshes) - len(flagged)) / len(report.meshes))
for target in report.profiles: print(target.name, ready_percent(report, target.name), "% ready")print("All targets", ready_percent(report), "% ready")Plan, apply and restore
Section titled “Plan, apply and restore”options = tailor.make_apply_options("Standard")options.nanite_mode = unreal.TALODTailorNaniteMode.KEEP_NANITE
# Dry run: [] = every mesh of the reportplan = tailor.plan(report, [], options)for entry in plan.entries: print(entry.name, entry.action, entry.old_lods, "->", entry.new_lods, list(entry.triangles), dict(entry.min_lod), entry.note)
result = tailor.apply(plan) # backs up firstprint(result.changed, "changed,", result.failed, "failed. Backup:", result.backup_file)
tailor.restore_backup(result.backup_file) # undo this runTo restore the newest backup that hasn’t been restored yet, pass an empty string: tailor.restore_backup("").
Only the meshes over the Meta Quest budget
Section titled “Only the meshes over the Meta Quest budget”over = [i.asset_path for i in report.issues if str(i.rule_id) == "OverBudget" and "Meta Quest" in i.targets]plan = tailor.plan(report, over, tailor.make_apply_options("Mobile aggressive"))Change the recipe
Section titled “Change the recipe”options = tailor.make_apply_options("Standard")preset = options.preset
step = unreal.TALODTailorLODStep()step.percent_triangles = 0.04step.distance = 160.0
lods = list(preset.lods)lods.append(step)preset.lods = lodsoptions.preset = preset
options.min_triangles = 2000tailor.preview_in_panel(options) # review it in the panel before applyingpreview_in_panel previews the meshes the panel has scanned; open the panel with a scan first, for example with open_panel_with_paths(["/Game/Props"]).
Skeletal meshes
Section titled “Skeletal meshes”options = tailor.make_apply_options_for("Standard", "Characters (mobile and VR)")options.include_static_meshes = False # only the skeletal meshesoptions.remove_unskinned_bones = True # from LOD 2 onoptions.remove_bones_from_lod = 2
plan = tailor.plan(report, [], options)for entry in plan.entries: print(entry.name, entry.action, list(entry.triangles), list(entry.bone_influences), entry.removes_bones)See Skeletal meshes.
Fewer draw calls
Section titled “Fewer draw calls”options = tailor.make_apply_options("Standard")options.reduce_draw_calls = Trueoptions.draw_calls_from_lod = 2options.drop_sections_below = 0.02 # 2 %
plan = tailor.plan(report, [], options)for entry in plan.entries: if entry.reduces_draw_calls: print(entry.name, list(entry.sections_before), "->", list(entry.sections_after))
tailor.export_plan(plan, tailor.get_default_export_options()) # lod_plan.html, .csv, .jsonSee Fewer draw calls.
Nanite or LODs
Section titled “Nanite or LODs”for advice in report.nanite_advice: if advice.verdict == unreal.TALODTailorNaniteVerdict.NANITE_WITH_FALLBACK_LODS: print(advice.name, advice.reason) for target in advice.targets: print(" ", target.target, target.verdict, target.reason)
cliff = unreal.load_asset("/Game/Props/SM_Cliff_Nanite")advice = tailor.advise_nanite(cliff)print(advice.verdict, advice.nanite_bytes, advice.lod_bytes, advice.material_risk, list(advice.notes))LOD pictures
Section titled “LOD pictures”barrel = unreal.load_asset("/Game/Props/SM_Barrel_LODs")if tailor.can_render_lod_pictures(): print(tailor.save_lod_pictures(barrel, "Saved/LODPictures", 256))
options = tailor.get_default_export_options()options.max_picture_meshes = 20result = tailor.export_report(report, options)print(result.lod_pictures, "LOD pictures in", result.main_file)Shared settings and folder rules
Section titled “Shared settings and folder rules”# Targets, presets and folder rules in an asset the team checks inconfig = tailor.create_settings_asset("/Game/Settings/DA_LODTailor", True)
# Copy them to another projecttailor.export_settings("C:/Shared/LODTailorSettings.json")# ... and in the other project:# tailor.import_settings("C:/Shared/LODTailorSettings.json")
for rule in tailor.get_folder_rules(): print(rule.path, rule.meshes, rule.preset, rule.apply_on_import)A script that imports many meshes can call tailor.apply_pending_import_rules() after each import, so the folder rules that apply on import run right away.
Reimport and log
Section titled “Reimport and log”statue = unreal.load_asset("/Game/Props/SM_Statue_Imported")tailor.reimport_keeping_imported_lods(statue) # imported LODs survive the reimport
for entry in tailor.get_log(): print(entry.time, entry.severity, entry.message)Reports
Section titled “Reports”options = tailor.get_default_export_options()options.output_directory = "Docs/LODReport"options.csv = Falseresult = tailor.export_report(report, options)print(result.main_file, result.errors)Distances
Section titled “Distances”targets = {t.name: t for t in tailor.get_targets()}quest = targets["Meta Quest"]
# A mesh with a 100 cm bounds radius, 9 m away on the Meta Quest camerasize = unreal.TALODTailorSubsystem.distance_to_screen_size(quest, 100.0, 9.0) # 0.0868meters = unreal.TALODTailorSubsystem.screen_size_to_distance(quest, 100.0, size) # 9.0
# Where LOD 1 of a scanned mesh takes over on Meta Quest (screen size for its key)mesh = report.meshes[0]if len(mesh.lods) > 1: lod1 = mesh.lods[1] screen = lod1.platform_screen_sizes.get(quest.platform, lod1.screen_size) print(unreal.TALODTailorSubsystem.screen_size_to_distance(quest, mesh.bounds_radius, screen))The last example looks only at the exact platform key; the panel also falls back to the key’s platform group (for example Mobile for Android) before the default screen size.