Skip to main content

Errant Paths 1.1

· 9 min read

image

This update makes Path manipulation far more intuitive and efficient, introduces texture-based terrain deformation and brings a variety of improvements, fixes, and optimizations.

Improved Path manipulation, spawning and connecting

  • You can snap new Path points to other Paths with Ctrl + Q. This action also automatically connects Paths together.
  • You can now spawn Paths starting at an existing Path:

Or spawn a new Path starting in the middle of one Path, and ending in the middle of another Path:

  • When spawning an intersection, you can align its rotation with existing Paths and the intersection will automatically cut nearby Paths and connect to them:

You can even add an intersection onto two crossed roads and it will cut and connect to them correctly.

  • You can replace a section of a Path with another Path (press R). Here we replace a 3-lane highway with a 4-lane highway.
  • You can spawn or extend a Path by following an existing Path:
  • You can now cut Paths with precision:
  • Connect individual ends of a Path with another Path:
  • Visualize existing connections between Paths and disconnect individual connections:
  • And when there are multiple overlapping ends to connect to, you can cycle between them by clicking the middle mouse button. The glow shows to which Path you will connect.
  • You can now adjust the arrive/leave tangents separately in PathSpline points, while their direction stays aligned.

Landscape Adjustment

Adjustment Spline

  • One of the less known features of Errant Paths was that meshes in PathTemplate could alter the landscape adjustment spline (e.g. make it zig-zag to match the asphalt shape) if their bAffectsLandscapeBiomesAdjustmentSpline property was set. This added unnecessary complexity to our codebase and wasn't intuitive, so we decided to replace this feature with a more elegant solution.

  • Landscape adjustment is now defined in a dedicated spline - EpLandscapeAdjustmentSplineComponent that can be manipulated directly and intuitively.

image

Defining adjustment in a separate spline opens up new possibilities! You could for example add a SpawnCondition for that spline to control landscape adjustment via PathLabels or add multiple adjustment splines within a single PathTemplate.

note

Configuring landscape adjustment via PathSplines is still supported but is deprecated and will be removed in the next release.

To make the transition to the new solution easier, we added a batch tool that processes all the PathTemplates and replaces adjustment configured in PathSplines with the new adjustment spline. To run this tool, click on the notification that shows up when you open the Errant Paths Editor Mode after the plugin upgrade. Or you can enter Project Settings -> Errant Paths and select bBatchUpgradePathTemplates checkbox.

image

Additive, texture-based landscape adjustment

  • You can now drive landscape adjustment with textures (e.g., noise, heightmaps), alongside curves. This allows creating realistically looking rivers, dirt paths, and embankments.

image

  • The best results come from applying texture-based adjustment as an additive over normal landscape adjustment. To make this possible, we've added support for multiple adjustment strategies, including an "Additive" Operator. Some options are only available when this Operator is used.
note

We currently support height and falloff/influence from textures. Weightmaps/BiomesMasks are not yet supported.

Improved Curve Editor

  • Editing landscape adjustment curves is now easier. We added an overlay that highlights valid regions of the graph, reducing the chance of errors.

image

Internal longitudinal adjustment

  • We added Internal Longitudinal Landscape Adjustment - primarily for controlling the steepness of tunnel entries.

    Internal Longitudinal Landscape Adjustment shape is controlled via a curve. These internal regions appear not only at Path start/end but also wherever adjustment settings change (e.g., road → tunnel transitions). A Path can therefore have multiple internal regions, which works seamlessly with conditional spawning. For example, a Path having multiple tunnels will have an "internal" regions at each entry/exit to the tunnel.

Spawning

  • New GroupComponent (EpPathTemplateGroupComponent) lets you apply a single SpawnCondition to a group of components. It can also be used to spawn a group of components with a certain Spawn Probability or to Spawn Only One Child from the group.

    What makes GroupComponent unqiue is that it's not spawned in the level and doesn't affect the transform of its children. Its children are spawned as if they were attached to the parent of the Group Component. For example, if your hierarchy is SplineMesh -> GroupComponent -> SplineMesh, it will spawn as if the hierarchy was SplineMesh -> SplineMesh. So the child SplineMesh will correctly bend with the parent.

image

  • You can now choose which InstanceStaticMesh (ISM) class to spawn for a given mesh (e.g., an ISM that can be interacted with via our Errant Instance Interaction plugin).

image

  • You can now remove overlapping copies of the same mesh, with configurable overlap margins (e.g. foliage can overlap more than rocks).
  • New PathLabels - "EPL_IsPathConnectedAtStart"/"EPL_IsPathConnectedAtEnd" will tell you whether a Path is connected to other Paths.

image

  • We deprecated PathLayerOverride. Originally, it was needed to handle assets created before EP 1.0 release. However, it introduced complexity and cluttered UI for a marginal gain in flexibility. We plan to remove this feature in the next plugin version. Please, configure PathLayers directly in the PathTemplate instead. A warning icon now appears if PathLayerOverride is enabled. We plan to release a new version of the AssetLibrary that doesn't use the override.

image

  • Child components must now have an equal or higher SpawnOrder than their parents. This reduces the number of difficult edge cases we need to handle and makes generation faster by reducing the number of temporary components that are spawned. A Blueprint compilation error will alert you when this occurs.

Improvements

  • Clicking a PathLabel while holding Shift/Ctrl/Alt shows only that PathLabel, hiding all the other PathLabels.
  • PathLayer can be set for multiple components at once.
  • SpawnConditions can be copy-pasted.
  • You can no longer add points to intersections with Ctrl + Q, as this was rarely intentional.

  • PathSpline points are easier to click as pink visualization is always rendered behind them.

  • Cursor location is calculated more reliably when cutting elevated or steep Paths.

  • Generation is triggered automatically after certain operations (adding a new point to a Path, connecting, merging, cutting, etc).

  • Viewport messages and inputs are now context-aware - they depend on the action being performed.

image

  • Meshes' bSpawn property was replaced with a more descriptive enum.

image

  • PathLabel "IsAboveOrUnderOtherPath" (renamed to "EPL_OverlapsAnotherPath") now functions correctly even when Paths don't have collision, thanks to our new internal overlap detection system. This PathLabel is typically used to disable Runtime Virtual Texturing in areas where roads overlap, preventing RVT artifacts.
  • We hid height-related properties in Weightmap/BiomeMasks adjustment properties in SplineStrategy to declutter UI.

Fixes, system reworks and optimizations

  • Path generation is now excluded from transactions, making Undo/Redo faster and more reliable. We also improved handling of undo/redo in PathLabel painting.

  • We dramatically improved the generation time for long Paths by introducing Grid-based spatial partitioning in multiple systems (aligning neighbor meshes, attachments, PathLabel evaluations) which allowed us to quickly find components spawned in a given volume.

  • We completed a complex rework of our spawning logic - instead of spawning individual meshes and then grouping them and converting them to instances, we now spawn instances directly. This allows us to spawn new instances faster and saves generation time that was spent on converting mesh components to instances. Despite this rework, we managed to find a way to keep the user interface mostly unchanged, appearing as if user was operating on individual meshes. Thanks to that, existing GenerationCallbacks continue working correctly.

  • We reworked our algorithm for PathTemplate rescaling. PathTemplate rescaling stretches PathTemplates slightly to make them match the Path length perfectly. The rework fixed a number of critical bugs where PathTemplates where shifted out of place.

  • We also reworked our spawning logic from plain function calls into SpawnTasks. This allowed us to better keep track of the relationship between the PathTemplate components that weren't spawned yet and their parents that have already been spawned, during the generation. This resulted in fewer temporary components spawned and allowed us to handle certain difficult cases more reliably.

  • We improved framerate when PathLabel visualization is displayed for long Paths. We now cache and reuse visualization geometry instead of recreating it every frame.

  • We now evaluate PathLabels incrementally, which helps avoid hitches during the generation, especially for long Paths and PathLabels with complex logic.

  • We optimized the algorithm for finding a PathLabel data point (binary search instead of linear search). Additionally, we don't evaluate PathLabels for disabled SpawnConditions anymore.

  • Internal landscape adjustment meshes are now generated slightly faster due to our use of FastBuild option.

  • Example map (BasicMap1) now uses the non-weight-blended workflow, to follow our own guidelines for procedural workflows.

  • Fixed a crash when entering a plugin Editor Mode while the license is being checked and a notification is shown.

  • Fixed ghost SubActors appearing after Undo.

  • We now correctly respawn a SubActor if its class was changed in properties.

  • Viewport messages are now hidden when Game View is enabled.