Skip to content

Writing A Program

Warning

This is still a work in progress. The API is still changing and thus this code may not work properly.

Why Program?

For programmers or anyone with a good handle of Roblox Lua, it can be faster than setting it up manually. Additionally, the GUI is still a work in progress, so you still have access to all of the API.

What is a Program?

ModuleScript that returns a function. This function takes the API as it's argument

The API is passed in as an argument instead of injected into the script environment as Roblox would yell at you for errors.

Track Setup

As there are a ton a points, we will set this up via Instance.

Setup Points

Requires that the points be named in order from start to end.

TheEpicTwin's Edit of Spacek's Coaster Plugin

OrderedPoints

local trackPoints = workspace:FindFirstChild("Track")

local cframeTrack = PointToPoint2Builder.new()
    :WithName("MyTrack")
    :WithPoints(trackPoints)
    :WithIsCircuited(true)
    :WithHashInterval(10)
    :Finish()

Program API

  • CFrameTrack
  • Segment
  • Section
  • TrackGroup
  • PhysicsRails

CFrameTrack a 3D line that defines the position of the track.

Segment builds a Part or Model from on a start and an end CFrame.

Section builds segments from a start and end position for a given track.

TrackGroup builds multiple sections for a track from a start and end position.

Segments:

  • Rail
  • TrackObject
  • MidTrackObject
  • Crossbeam
  • Rect
  • RectRail
  • BoxRail

For now, we will only be using 3. Check the examples if you would like to see how the others are used.

Left Rail

local RailSegmentBuilder = Segment.RailBuilder

local leftRailSection = SectionBuilder.new()
    :WithName("LeftRail")
    :WithSegment(RailSegmentBuilder.new()
        :WithBasePart(RAIL_PART)
        :WithOffset(Vector3.new(-3, 0, 0))
        :WithHorizontal(true)
        :WithMeshData(MeshDataBuilder.new()
            :WithMesh("CylinderMesh")
            :WithOffset(Vector3.new(0, 0, 0))
            :WithScale(Vector3.new(1, 1, 0.2))
            :Finish()
        )
        :Finish()
    )
    :WithSegmentLength(5)
    :WithSectionStart(0)
    :WithOptimize(true)
    :WithBuildEnd(false)
    :Finish()

Right Rail

local rightRailSection = SectionBuilder.new()
    :WithName("RightRail")
    :WithSegment(RailSegmentBuilder.new()
        :WithBasePart(RAIL_PART)
        :WithOffset(Vector3.new(3, 0, 0))
        :WithHorizontal(true)
        :WithMeshData(MeshDataBuilder.new()
            :WithMesh("CylinderMesh")
            :WithOffset(Vector3.new(0, 0, 0))
            :WithScale(Vector3.new(1, 1, 0.2))
            :Finish()
        )
        :Finish()
    )
    :WithSegmentLength(5)
    :WithSectionStart(0)
    :WithOptimize(true)
    :WithBuildEnd(false)
    :Finish()

Tie

local tieSection = SectionBuilder.new()
    :WithName("Tie")
    :WithSegment(TrackObjectSegmentBuilder.new()
        :WithTrackObject(TIE_PART)
        :WithOffset(CFrame.new(0, 0, 0))
        :Finish()
    )
    :WithSegmentLength(5)
    :WithSectionStart(0)
    :WithOptimize(true)
    :WithBuildEnd(false)
    :Finish()

Crossbeam

local crossbeamSection = SectionBuilder.new()
    :WithName("Crossbeam")
    :WithSegment(CrossbeamSegmentBuilder.new()
        :WithBasePart(CROSSBEAM_PART)
        :WithStartOffset(Vector3.new(3, 0, 0))
        :WithEndOffset(Vector3.new(-3, 0, 0))
        :Finish()
    )
    :WithSegmentLength(5)
    :WithSectionStart(0)
    :WithOptimize(true)
    :WithBuildEnd(false)
    :Finish()

Build

local trackGroup = TrackGroupBuilder.new()
    :WithName("MyTrack")
    :WithSection(leftRailSection)
    :WithSection(rightRailSection)
    :WithSection(tieSection)
    :WithSection(crossbeamSection)
    :Finish()
local trackModel = trackGroup:Create(
    cframeTrack,
    0,
    cframeTrack.Length
)

trackModel.Parent = workspace

Full Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
return function(api)
    local TrackGroup = api.TrackGroup
    local Section = api.Section

    local CFrameTrack = api.CFrameTrack
    local PointToPoint2Builder = CFrameTrack.PointToPoint2Builder

    local Segment = api.Segment
    local RailSegmentBuilder = Segment.RailBuilder
    local TrackObjectSegmentBuilder = Segment.TrackObjectBuilder
    local CrossbeamBuilder = Segment.CrossbeamBuilder

    local trackPoints = workspace:FindFirstChild("Track")

    local cframeTrack = PointToPoint2Builder.new()
        :WithName("MyTrack")
        :WithPoints(trackPoints)
        :WithIsCircuited(true)
        :WithHashInterval(10)
        :Finish()

    local leftRailSection = SectionBuilder.new()
        :WithName("LeftRail")
        :WithSegment(RailSegment.new()
            :WithBasePart(RAIL_PART)
            :WithOffset(Vector3.new(-3, 0, 0))
            :WithHorizontal(true)
            :WithMeshData(MeshDataBuilder.new()
                :WithMesh("CylinderMesh")
                :WithOffset(Vector3.new(0, 0, 0))
                :WithScale(Vector3.new(1, 1, 0.2))
                :Finish()
            )
            :Finish()
        )
        :WithSegmentLength(5)
        :WithSectionStart(0)
        :WithOptimize(true)
        :WithBuildEnd(false)
        :Finish()

    local rightRailSection = SectionBuilder.new()
        :WithName("RightRail")
        :WithSegment(RailSegmentBuilder.new()
            :WithBasePart(RAIL_PART)
            :WithOffset(Vector3.new(3, 0, 0))
            :WithHorizontal(true)
            :WithMeshData(MeshDataBuilder.new()
                :WithMesh("CylinderMesh")
                :WithOffset(Vector3.new(0, 0, 0))
                :WithScale(Vector3.new(1, 1, 0.2))
                :Finish()
            )
            :Finish()
        )
        :WithSegmentLength(5)
        :WithSectionStart(0)
        :WithOptimize(true)
        :WithBuildEnd(false)
        :Finish()

    local tieSection = SectionBuilder.new()
        :WithName("Tie")
        :WithSegment(TrackObjectSegmentBuilder.new()
            :WithTrackObject(TIE_PART)
            :WithOffset(CFrame.new(0, 0, 0))
            :Finish()
        )
        :WithSegmentLength(5)
        :WithSectionStart(0)
        :WithOptimize(true)
        :WithBuildEnd(false)
        :Finish()

    local crossbeamSection = SectionBuilder.new()
        :WithName("Crossbeam")
        :WithSegment(CrossbeamSegmentBuilder.new()
            :WithBasePart(CROSSBEAM_PART)
            :WithStartOffset(Vector3.new(3, 0, 0))
            :WithEndOffset(Vector3.new(-3, 0, 0))
            :Finish()
        )
        :WithSegmentLength(5)
        :WithSectionStart(0)
        :WithOptimize(true)
        :WithBuildEnd(false)
        :Finish()

    local trackGroup = TrackGroupBuilder.new()
        :WithName("MyTrack")
        :WithSection(leftRailSection)
        :WithSection(rightRailSection)
        :WithSection(tieSection)
        :WithSection(crossbeamSection)
        :Finish()

    local model = Instance.new("Model")

    local trackModel = trackGroup:Create(
        cframeTrack,
        0,
        cframeTrack.Length
    )
    trackModel.Parent = model

    local chainLiftModel = chainLiftSection:Create(
        cframeTrack,
        100,
        200
    )
    chainLiftModel.Parent = model

    local brakesModel = brakesSection:Create(
        cframeTrack,
        400,
        500
    )
    brakesModel.Parent = model

    model.Parent = workspace
end