Building Trains
Introduction
This is the tutorial on how to build and script a working train. This will show you how you can get your own rapid transit rail system going.
Auto Start Trains
This section deals with making trains that will automatically start, travel to a destination, wait one minute, and return to their starting location.
Building
Map
First of all, before we can script we need something for the train to travel on. Create a new map with a single block with a size of about 200 x 200. Anchor this block and lock it.
Rails
Next, we need rails. Start off by placing a light gray block into the map. Resize this block to be 2 wide, 1 tall, and 150 deep. Set the friction to about 0.1 (you can play with the values, it just helps it run smoothly). Also make sure to set the top surface to smooth. Now copy this block but make it 1 wide. Set the bottom surface to Weld. Place this block on top and to the left of the first one. You should now have a shiny smooth L shaped rail. Group these two blocks.
Copy the first rail, rotate it 180 degrees and place it about 12 studs to the right of the first one. The rails should be evenly positioned. Group both the rails. Anchor and lock them:
Engines
The train building part is really up to you, but some things are necessary for the operation of this train. The method I will show you is what I call a Static Engine Block. To start, put a single white block in the map. Set the bottom surface to smooth. You will also need to set the friction to 0. Place this block on the rail so that one stud is over the rail and one is off. It should fit perfectly in the L shape of the rail. Now with this block selected go up to Insert -> Object. When the browser appears find and select BodyVelocity. Make sure the "Velocity" is 0 or else it will move in an un-wanted direction during the building process. Now in the explorer change the name of this block to "Engine1". Open it up and find the newly added BodyVelocity class (it's the only other child). Now in the properties set the Value for "P" to 9.9e+005. And set the value for "MaxForce" to 0,0,9.9e+005. Copy this block and put it over to the other rail. Rename it "Engine2". It's very important that these two blocks are even and that all the spelling is right. These two blocks will power the whole train. Place a dark gray block on top of the engine and stretch it across to the other one. Copy the two Engine blocks and place them a few studs behind the first ones. Remove the Body Velocity classes from these two. And rename them to something like "Supports", these two aren't important. They will keep the train even. Stretch the dark gray block over the engines down to cover these two new blocks. You should now have an even and flush square. This is your train engine. Add whatever you want now on top of the dark gray platform. Just don't make it so nothing touches the side of the rails except the engines.
Workings of an Auto Start Train
All we really have to do is: Start the train moving, wait long enough for it to reach its destination, wait a minute, start it moving backwards, give it enough time to arrive, wait another minute, and start again. We can easily make this loop endlessly using a while true do loop, like this.
while true do end
Whatever is between 'while true do' and 'end' will loop forever. Unless the script gets deleted, or the train gets destroyed, for example. So, if you have weapons that can deal major damage (Rocket Launchers, Bombs, etc.), a regen script would be helpful, as well.
Double Check
It's time to double-check. Now you should have a train model. The following must be direct children of that model, in order for this to work: Engine1, Engine2. Once your train is made and you've double-checked, insert a script as a direct child of the model, too.
Need To Know
Now that you've double-checked, it's time to start the scripting. Before we do, you should understand the following:
Body Velocity
'Body Velocity', sometimes called just 'Velocity', but referred by GoodBlox Studio as 'BodyVelocity', is what moves objects. An object with BodyVelocity will move in the direction defined in its Vector3 coordinates. Of course, it can't make an object move THROUGH others (unless CanCollide is false).
while true do
'while true do' is a very simple, and common, script line. It was explained briefly in the "Starting Off - How To?" section, above.
The Scripting
If the script is a direct child of the Train model, all you should have to do is insert the following code into the script.
E1 = script.Parent.Engine1 E2 = script.Parent.Engine2 while true do wait(60) E1.BodyVelocity.velocity = Vector3.new(0, 0, 20) -- Change 20 to change the speed. E2.BodyVelocity.velocity = Vector3.new(0, 0, 20) wait(#) -- Replace # with the # of seconds it takes your train to reach its destination. E1.BodyVelocity.velocity = Vector3.new(0, 0, 0) -- Stop the train. E2.BodyVelocity.velocity = Vector3.new(0, 0, 0) wait(60) E1.BodyVelocity.velocity = Vector3.new(0, 0, -20) E2.BodyVelocity.velocity = Vector3.new(0, 0, -20) wait(#) E1.BodyVelocity.velocity = Vector3.new(0, 0, 0) E2.BodyVelocity.velocity = Vector3.new(0, 0, 0) end
This gives us a basic platform that automatically goes back and forth, with a one-minute delay between trips. You can add a message for when the train is about to take off, you can change the speed, and you can randomize the wait period between rides.
One-Way Trains
Here is a script that you can use instead to make a train just go one way. This can be useful for suicide rides.
E1 = script.Parent.Engine1 E2 = script.Parent.Engine2 while true do wait(60) E1.BodyVelocity.velocity = Vector3.new(0, 0, 20) -- Change 20 to change the speed. E2.BodyVelocity.velocity = Vector3.new(0, 0, 20) end
More advanced
Body Suggestions
Make sure whatever is built on the original platform can actually be boarded. It's no fun if no one can get in your train. Also, any thing else built on top of the platform should be grouped by itself. I usually name the body group "BodyKit". This will make it easy to copy and redesign trains by only having to delete the BodyKit group and having bare bones left.
Controls
If you don't want to have the train run automatically, controls are needed to operate the train. Many options are available for controlling this, but I find the easiest for beginners to make and operate is Touch Buttons, these are buttons that you physically touch with your player to control the train. Like the engines, these need to be named properly.
1) Insert a green brick.
2) Resize that green brick to 3x1x3.
3) Smooth the top of it.
4) Rename that brick "Go".
5) Place the "Go" brick on the control room floor.
6) Copy the "Go" brick.
7) Place the newly copied brick next to the old "Go" brick on the control room floor.
8) Color the newly copied brick red.
9) Name the red brick "Stop".
10) Copy the "Stop" brick.
12) Place the newly copied brick next to the old "Stop" brick on the control room floor.
13) Color this newly copied brick yellow.
14) Name the yellow brick "Shift".
15) The "Shift" brick will be for going in reverse.
Prepping for Scripting
The scripts will not search for blocks. Everything needs to be named correctly and positioned and placed properly in its right place. This means by trying to organize things and grouping the engines separate from the buttons will break your train. So first. Everything for the train (except rails) should now be grouped. The Hierarchy should look like this:
[Train Group] |-[BodyKit Group] | |-Extra pieces for looks |-"Engine1" | |-BodyVelocity |-"Engine2" | |-BodyVelocity |-"Go" |-"Stop" |-"Shift" |-Grey Platform
Scripting
Select the Train Group and go up to Insert -> Object. When the prompt for class shows up select script. A script should now appear in the Train Group under the Explorer window. Name it "TrainConductor" (make sure you deleted the script from the Auto Start Train above, if it still exists). Double click it to open it up. The view of your map should now change to a blank document except for the words "print("Hello World!")".
Below that enter these lines:
bin = script.Parent engine1 = bin.Engine1 engine2 = bin.Engine2 go= bin.Go stop= bin.Stop shift= bin.Shift hold = false --Keep from lagging and multiple touches dir = 1 --What gear we are in (forward=1, reverse=-1) active = false --Make sure we can't shift in movement. cur_spd = 0 max_spd = 20
This is telling us where each block is and what we are going to call it in the script. The last two lines are for holding the current speed. You can play with the value in max_spd but I wouldn't set it above 40. This is the fastest the train will go. Now I'm not going through the fancy gradual speed up stuff. This is strictly go or stop. Next add these lines:
function onTouch_Go(part) local h = part.Parent:findFirstChild("Humanoid") if (h~=nil and hold==false) then --Player touched Go Button hold=true go.Color = Color3.new(0,0,0) --Show that this button is active active = true engine1.BodyVelocity.velocity = Vector3.new(0,0,max_spd*dir) engine2.BodyVelocity.velocity = Vector3.new(0,0,max_spd*dir) wait(2) --How long to wait before accepting more button pushing go.Color = Color3.new(0,1,0) --Set button back to green hold=false end end go.Touched:connect(onTouch_Go)
This will now make our train move forward so far. It registers when the Go button has been pressed and sets the engine speed accordingly. It even shows that the button was pressed and when it can be pressed again. But the train still needs to stop so add these lines:
function onTouch_Stop(part) local h = part.Parent:findFirstChild("Humanoid") if (h~=nil and hold==false) then --Player touched Stop Button hold=true stop.Color = Color3.new(0,0,0) --Show that this button is active active = false engine1.BodyVelocity.velocity = Vector3.new(0,0,0) engine2.BodyVelocity.velocity = Vector3.new(0,0,0) wait(2) --How long to wait before accepting more button pushing stop.Color = Color3.new(1,0,0) --Set button back to red hold=false end end stop.Touched:connect(onTouch_Stop)
Now we can stop the train by setting the Engine speed to 0. If we want to be able to go in reverse then we will need to add these lines:
function onTouch_Shift(part) local h = part.Parent:findFirstChild("Humanoid") if (h~=nil and hold==false and active==false) then --Player touched Shift Button hold=true shift.Color = Color3.new(0,0,0) --Show that this button is active if (dir==1) then dir=-1 --Go in Reverse now else dir=1 --Go Forward now end wait(2) --How long to wait before accepting more button pushing shift.Color = Color3.new(1,1,0) --Set button back to yellow hold=false end end shift.Touched:connect(onTouch_Shift)
This is our final bit of code and will enable to train to go in reverse when pressed. But only if we are already stopped. I advise studying this code. Its the basic principle for anything involving user input. Your train should now move perfectly.
Building trains that speed up and slow down
This tutorial will teach you how to make trains that speed up and slow down when a part is at a certain CFrame.
Starting
To start, you need some rails.
Building the train
See basic structural building instructions above
To make the buttons to drive it, make a green brick that is 1 high, 2 wide. Name it go. Do the same for 2 more buttons but make one red and name it stop, the other yellow and called shift. Finally group them together and name it TrainGroup.
Body Kit
The body kit is up to you. It could be really blocky, or use meshes to get a nice sloped front and don't forget the seat(s) or else the riders will fall about, maybe out the train or onto the stop button. But the main thing is a door into it. When you make it, group it all, name it BodyKit and paste it into the train group.
Monorails
Monorails are pretty simple, if you already have a working train up and running.
1) Copy one of the rails from the train tracks (it doesn't matter which).
2) Rails are composed of two parts -- take the bottom piece and make it one stud wider. Instead of looking like an "L" it now looks like an upside down "T".
3) Copy the Engine1 and Engine2 bricks from the train and place them to the left and right of the newly laid monorail track.
4) Copy the two support bricks from the train and place them to the left and right of the newly laid track.
5) Copy the axles from the train and place them on top of the Engines and Supports, respectively.
6) Resize the axles to not be as wide -- because you're not stretching across two tracks anymore!
7) Copy the platform from the Train and paste it on top of your newly laid axles.
8) Group your parts together (but not the monorail track).
9) Experiment with this, for example, by inserting the "Auto Start Train" script into your newly created monorail train model.
10) It is important to edit the "Auto Start Train" script to remove any commands from that script to parts which you have removed (such as Engine2), otherwise you will get an error.
11) You can put the Auto start monorail on a ramp using a hinge, for example.
There is a lot you can do with this. For example, you can create a "U"-shaped rail, lengthen the Engine1, remove the Support part and its corresponding axle altogether, and narrow the top platform. You have a much more sleek looking Monorail, and you haven't even built the BodyKit yet. The "U" shape of the rail holds the Engine1 in place from falling off the track.
An onTouch script
Let's propose you don't want to walk on the buttons to change direction, but instead want to click the buttons. This script will allow you to click the Stop, Go, and Shift buttons instead. Replace the contents of the TrainConductor script with the following script. You will also need to add a ClickDetector into the Stop, Go and Shift buttons. If your train does not move, you may need to change a dimension (for example, change Vector3.new(0,0,max_spd*dir) to Vector3.new(max_spd*dir,0,0) ) :
bin = script.Parent engine1 = bin.Engine1 engine2 = bin.Engine2 go = bin.Go stop = bin.Stop shift = bin.Shift hold = false dir = 1 active = false max_spd = 20 function onTouch_Go() if (hold == false) then hold = true go.Color = Color3.new(0,0,0) active = true engine1.BodyVelocity.velocity = Vector3.new(0,0,max_spd*dir) engine2.BodyVelocity.velocity = Vector3.new(0,0,max_spd*dir) wait(2) go.Color = Color3.new(0,1,0) hold = false end end go.ClickDetector.MouseClick:connect(onTouch_Go) function onTouch_Stop() if (hold==false) then hold = true stop.Color = Color3.new(0,0,0) active = false engine1.BodyVelocity.velocity = Vector3.new(0,0,0) engine2.BodyVelocity.velocity = Vector3.new(0,0,0) wait(2) stop.Color = Color3.new(1,0,0) --Set button back to red hold = false end end stop.ClickDetector.MouseClick:connect(onTouch_Stop) function onTouch_Shift() if (hold == false) and (active == false) then hold = true shift.Color = Color3.new(0,0,0) if (dir == 1) then dir = -1 else dir = 1 end wait(2) shift.Color = Color3.new(1,1,0) hold = false end end shift.ClickDetector.MouseClick:connect(onTouch_Shift)
Train Troubleshooting
Your train may work fine, but it "glides" out of position after a while, and even off the track.
- Your rails and/or your engine/supports may be too slippery. Try making the friction of the rails and/or the engine/supports a little higher.
Your train flies angrily off the track when you start the program instead of sitting quietly.
- You may have a certain element of your script trying to send your train in a direction that the train can't go. For example, trying to send it in a left-right direction, but your track only goes forwards and backwards.