Skip to main content

Train Model Setup

This section will teach you how to "rig" a train model for use with the system.

See also CFrameTrain and AnimationModel

What is a Train

The basic principles of the system have been, since it's inception:

  • Tracks are 3-dimensional lines
  • A 1-dimensional position (number) can be converted to a 3-dimensional position (CFrame) on the line.

This ties into how trains are implemented.

The basic principles of a train are:

  • A train moves along the track at it's wheel sets.
    • This means the center line of the track should be at the center of it's rails
  • Wheel sets are stored as a set of 1D offsets on the track (positionOffsets).
  • Chassis and connectors are calculated from the 3D positions calculated from the wheel sets.

Some problems:

  • When traversing curves in the track, the cars may clip/collide into each other as it compresses with the turn.
    • It's more noticeable on Wing Coaster trains/wider trains.

These are all trade-offs for a simpler way of handling the train

Train Model Spec

The TrainModel Specification defines how to organize a train's Model so that it can moved around a track in a realistic (or close to) manner.

// Train Model/CFrameTrain Specification:
// - Anything that is an Instance is usually a Folder or Model. Just a Instance used to contain children.
// - Anything that is a Model will use the Model's PVInstance functions such as `GetPivot` and `SetPivot`
// - Anything postfixed with "?" is optional.
// - CFrameInstance is anything that can be converted into a CFrame.
// - PVInstance (BasePart or Model)
// - CFrameValue
// - Vector3Value
// - ObjectValue->CFrameInstance (max depth of 1)

TrainModel: Instance
+--> ModelType: StringValue // required for AnimationModel; Value should be set to "CFramedTrain"
+--> MidPoint: NumberValue
+--> Cars: Instance
| +--> 1: Instance
| | +--> CFrameCalculationType: IntValue // see CFrameCalculationType
| | +--> Chassis: Model
| | +--> WheelSetA: Model
| | +--> WheelSetB?: Model
| | +--> FrontConnector?: CFrameInstance
| | +--> RearConnector?: CFrameInstance
| |
| ...
| +--> N: Instance
| + ...
|
+--> Connectors: Instance
+--> 1: Model
| +--> FrontCarIndex: IntValue
| +--> RearCarIndex: IntValue
|
...
+--> N: Model
+ ...

Getting Started

Classic corkscrew train free model asset.

Initial Setup

  • Group all the cars together

    • Name the resulting Model Cars
  • Individually group each car

  • Group all the connectors together

    • Name the resulting Model Connectors

Train Model

type TrainModel = {
ModelType: StringValue,
MidPoint: NumberValue,

Cars: Instance,
Connectors: Instance,
}

ModelType

StringValue

This is used for AnimationModel for the Framework

Set it to CFramedTrain.

MidPoint

NumberValue

Determines where the "midpoint" of the train is. It's an alpha value compared to the train's length.

  • 0 is the front
  • 0.5 is the middle
  • 1 is the very back

This midpoint is used to calculate where the TrackSectionsData starts affecting a train's physics for that section.

Car Models

Children:

type CarModel = {
CFrameCalculationType: IntValue,
Chassis: Model,
WheelSetA: Model,
WheelSetB: Model?,
FrontConnector: CFrameInstance?,
RearConnector: CFrameInstance?,
}

CFrameCalculationType, Chassis, and WheelSetA are required

WheelSetA is considered the front-most wheel set, meaning WheelSetA is positioned in front of WheelSetB in the car.

WheelSetB is NOT required.

FrontConnector and RearConnector are used in calculating the Connector positions. This will be explained in the Connectors section.

CFrameCalculationType

Defines how the Chassis should be positioned relative to the Car's WheelSets.

enum CFrameCalculationType = {
FromWheelSetA = 0,
BetweenFrontCar = 1,
BetweenRearCar = 2,
BetweenWheelSets = 3,
}

FrontWheelSetA

FromWheelSetA gets the offset from this Car's WheelSetA.

This is usually used for zero cars.

BetweenFrontCar

BetweenFrontCar gets the offset from the middle of this Car's WheelSetA and the position from the Car in front of it's rear-most wheel set. If WheelSetB exists, the rear-most wheel set is WheelSetB, otherwise, it is WheelSetA. If the front car is not present, it defaults to FrontWheelSetA.

An example is a Car on a B&M Train other than the zero car.

BetweenRearCar

BetweenRearCar gets the offset from the middle of this Car's WheelSetA and the Car behind it's WheelSetA positions. It requires there to be a car behind this one, otherwise it will default to FrontWheelSetA.

An example is a Car on an Arrow Corkscrew train other than the zero car. The zero car is usually in the back for this model.

BetweenWheelSets

BetweenWheelSets gets the offset from the middle of the Car's WheelSetA and WheelSetB's positions. It requires both WheelSetA and WheelSetB to be present, otherwise defaults to FrontWheelSetA.

You don't need to set your CFrameCalculationType to BetweenWheelSets if you have a WheelSetB set, but it does make it look more accurate usually.

An example is a train which has two wheel sets on one car such as on a Vekoma Mine Train or a Wild Mouse.

Chassis

The chassis is the main body of the car. It usually contains the seats which the players will sit in.

WheelSets

Tips for getting the center position:

  • Use a PrimaryPart
  • Model.OriginPosition
    • Group two wheels which are roughly at the middle
    • Have Reset Pivot do all the work of getting the center
    • Copy the Position
    • Ungroup the Model you just made

Connectors

Connectors are positioned between cars and visually connect the cars to each other.

Children:

  • FrontCarIndex
  • RearCarIndex
type Connector: Model = {
FrontCarIndex: IntValue,
RearCarIndex: IntValue,
}
  • Gets the RearConnector position from the FrontCar
  • Gets the FrontConnector position from the RearCar

the following was taken almost verbatim from a comment

First, you need to setup FrontConnector and RearConnector in the Car Model so the connector has a reference to connect to. FrontConnector is where the Connector is connected at the Front of the Car while RearConnector is where it is in the rear.

If you noticed in the docs, these are CFrameInstances which are Instances that can be converted to CFrames. I recommend having FrontConnector and RearConnector be ObjectValues and inserting two Parts at the locations which your Connector connects to the Car. Finally set the Front and Rear Connector ObjectValues to those parts.

Next, you Connector needs to be a Model. Your connector must also have two IntValue children named FrontCarIndex and RearCarIndex which you set to the Name/Index of the car you want this connector to connect to.

Seat Setup

Changed from v1, the RideSeatPlugin will now look for any descendant of the TrainModel that is a Seat, so you don't need to do any fancy setup. This comes at a cost of being able to individually control the seats in cars and rows.