WorldTangent

WorldTangent

#Overview

name: WorldTangent

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 3 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of WorldTangent is to represent the tangent vector of a spline or curve in world space within Unreal Engine 5’s ZoneGraph system. This variable is used to calculate and store the direction of a curve at specific points, which is crucial for smooth path generation and navigation in game environments.

WorldTangent is primarily used in the ZoneGraph module, which is part of Unreal Engine 5’s runtime plugins. This module is responsible for creating and managing navigable zones and paths in game worlds.

The value of WorldTangent is typically calculated within the code, rather than being set directly. It is computed using the positions of adjacent points on a spline or curve, as seen in the provided code excerpts.

WorldTangent interacts with other variables such as LanePoints, LaneTangentVectors, and component transforms. It is often used in conjunction with these variables to define the shape and direction of paths or lanes in the game world.

Developers must be aware that WorldTangent is a normalized vector, representing only the direction of the tangent, not its magnitude. It’s crucial to ensure that the points used to calculate WorldTangent are not coincident, as this could result in a zero-length vector and potential errors.

Best practices when using WorldTangent include:

  1. Always normalize the vector to ensure consistent behavior.
  2. Handle edge cases where adjacent points might be identical to avoid division by zero errors.
  3. Use WorldTangent in conjunction with other spline data (like position and curvature) for accurate path representation.
  4. When transforming WorldTangent between local and world space, use the appropriate transform methods (TransformVector for directions, not TransformPosition).
  5. Consider caching WorldTangent values when performance is critical, as recalculating for each use might be computationally expensive in complex scenes.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEngine.ini:2919, section: [Engine.BufferVisualizationMaterials]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Plugins/Runtime/ZoneGraph/Source/ZoneGraph/Private/ZoneShapeUtilities.cpp:963

Scope (from outer to inner):

file
namespace    UE::ZoneShape::Utilities
function     void TessellateSplineShape

Source code excerpt:

		for (int32 PointIndex = Lane.PointsBegin + 1; PointIndex < Lane.PointsEnd - 1; PointIndex++)
		{
			const FVector WorldTangent = (OutZoneStorage.LanePoints[PointIndex + 1] - OutZoneStorage.LanePoints[PointIndex - 1]).GetSafeNormal();
			OutZoneStorage.LaneTangentVectors.Add(WorldTangent);
		}

		if (LaneDesc.Direction == EZoneLaneDirection::Forward)
		{
			OutZoneStorage.LaneTangentVectors.Add(EndForward);
		}

#Loc: <Workspace>/Engine/Plugins/Runtime/ZoneGraph/Source/ZoneGraph/Private/ZoneShapeUtilities.cpp:1711

Scope (from outer to inner):

file
namespace    UE::ZoneShape::Utilities
function     static void BuildLanesBetweenPoints

Source code excerpt:

		for (int32 PointIndex = 1; PointIndex < NumNewPoints - 1; PointIndex++)
		{
			const FVector WorldTangent = (NewPoints[PointIndex + 1] - NewPoints[PointIndex - 1]).GetSafeNormal();
			OutZoneStorage.LaneTangentVectors.Add(WorldTangent);
		}
		OutZoneStorage.LaneTangentVectors.Add(-DestSlot.Forward);
	}
}

float GetPolygonBoundaryTessellationTolerance(TConstArrayView<FZoneLaneProfile> LaneProfiles, const FZoneGraphTagMask ZoneTags, const FZoneGraphBuildSettings& BuildSettings)

#Loc: <Workspace>/Engine/Plugins/Runtime/ZoneGraph/Source/ZoneGraphEditor/Private/ZoneShapeComponentVisualizer.cpp:1385

Scope (from outer to inner):

file
function     bool FZoneShapeComponentVisualizer::HandleSnapTo

Source code excerpt:

						const FVector WorldPosition = ShapeComp->GetComponentTransform().TransformPosition(EditedPoint.Position);
						const FVector WorldInControlPoint = ShapeComp->GetComponentTransform().TransformPosition(EditedPoint.GetInControlPoint());
						const FVector WorldTangent = WorldInControlPoint - WorldPosition;
						FVector NewTangent = DeltaRotate.RotateVector(WorldTangent);
						NewTangent = ShapeComp->GetComponentTransform().InverseTransformVector(NewTangent);
						EditedPoint.SetInControlPoint(EditedPoint.Position + NewTangent);
					}

					bMovedKey = true;
				}