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
- Name the resulting Model
Individually group each car
Group all the connectors together
- Name the resulting Model
Connectors
- Name the resulting Model
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 front0.5
is the middle1
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 CFrameInstance
s which are Instances that can be converted to CFrame
s.
I recommend having FrontConnector
and RearConnector
be ObjectValue
s and inserting two Part
s at the locations which your Connector
connects to the Car
. Finally set the Front
and Rear
Connector
ObjectValue
s 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.