Skip to content

Splines

A spline is a smooth curve through points you place: the route of a patrol boat, a rail a camera glides along, the line of a race track. Other entities can follow it, and scripts can ask where along it something is.

  1. Add an entity and give it Add Component > Spline. It starts as a short straight line of two points.
  2. With the entity selected, turn on Spline in the scene page’s toolbar.
  3. Shape it in the viewport:
    • Drag a point to move it.
    • Select a point to show its two handles, and drag a handle to bend the curve there. Shift while dragging lets the two handles point different ways, for a sharp corner.
    • Ctrl+click on the curve to add a point there.
    • Point at a point and press Delete (or X) to remove it. A spline keeps at least two.

Each change is one undo step. Closed in the inspector joins the last point back to the first, for a loop.

The points belong to the entity: move, turn or scale the entity, and the whole curve goes with it.

Give another entity a Path Follow component and set its Spline to the entity with the curve:

  • Speed: metres a second along the curve.
  • Distance: where along the curve it is, in metres. Set it to start part way along.
  • Playing: whether it moves.
  • Loop: at the end of an open curve, go back to the start. Without it, the follower stops at the end and Playing turns off. A closed curve always goes round.
  • Align To Tangent: face along the curve as it goes.

It moves only while the game plays. The follower should not have a parent.

function Boat:onUpdate(dt)
local follow = PathFollowComponent.of(self.entity)
if Input.wasPressed("Fire") then
follow.playing = not follow.playing
end
end

SceneSplines measures a curve and finds points on it. Each call takes the entity with the spline:

function Rival:onUpdate(dt)
local track = self.entity.scene:find("RacingLine") -- the entity with the spline
local splines = SceneSplines.of(self.entity.scene)
local here = splines:closestPoint(track, self.entity:worldPosition())
local ahead = splines:sampleAtDistance(track, here.distance + 10.0)
Log.info("lap " .. here.distance / splines:length(track))
-- ahead.position is where to steer; ahead.tangent the way the track runs there
end
  • length(entity) is the curve’s length in metres.
  • sampleAtDistance(entity, distance) is the point that far along.
  • closestPoint(entity, position) is the point on the curve nearest a position, and how far along it is.
  • sampleAt(entity, t) takes a position by segment instead: 0 is the first point, 1 the second, and so on.

Each gives back valid, position, tangent (the direction there), distance and t, in world space. Scripts read curves; they cannot move a curve’s points.