|
|
Line 1: |
Line 1: |
| | <!-- The guide before didn't include vehicle seats, and that's what we wanted, right? --> |
| | Have you ever wanted to create a car from scratch using [[RBX.lua.VehicleSeat (Object)|VehicleSeats]]? VehicleSeats can make any object move with no scripting involved. You don't have to learn Lua to make cars anymore! This tutorial will explain how! |
| __TOC__ | | __TOC__ |
| | | == How VehicleSeats Work == |
| == Introduction == | | VehicleSeats work by finding all of the hinges in a model. Using all of the hinges in a model, the vehicleseat rotates the parts with the hinges so that the car moves. The game does all of the hard work for you, leaving you to build magnificent cars! |
| | | == How Do I Use VehicleSeats? == |
| This tutorial will demonstrate the basic steps needed to build a car from scratch. The scripts used to make the car move are derived from the basic plane scripts. In that sense, the car has many of the same key objects as the plane. For this tutorial, the plane scripts have been simplified and customized to make them car-specific. In addition, the type of car described in this tutorial moves by the rotation of the wheels, not by applying Velocity to the engine brick.
| | A VehicleSeat acts as a part, or a seat to be more specific. When you sit in a VehicleSeat, a signal gets sent that moves the car when you move. It's an amazing system to make a simple car. |
| | | == Lets Make A Car! == |
| == Creating a Car From Scratch ==
| | As you can see, making cars is easy with VehicleSeats. You must have a basic knowledge of building, though. <!-- add on to the guide. Not done. --> |
| | |
| These instructions describe the building of the car within Roblox Studio.
| |
| | |
| The car will consist of these models:
| |
| *CarGarage
| |
| *Car
| |
| *Parts
| |
| *BodyKit
| |
| | |
| === Creating the CarGarage Model ===
| |
| | |
| The purpose of CarGarage model is basically to hold the script needed to re-generate the car after a player drives away. Follow these steps to create the '''CarGarage''' model and add the necessary objects which will allow the car to regenerate.
| |
| | |
| *In the Explorer window, select the Workspace
| |
| *From the Insert menu, select Object > Model
| |
| *Rename this new model '''CarGarage'''
| |
| *Select the new '''CarGarage''' model
| |
| *From the Insert menu, select Object > IntValue. Rename this value '''Regen'''
| |
| *Select the '''CarGarage''' model, and insert a Script object. Rename this script '''RegenScript'''. Add the following code into the script.
| |
| | |
| <pre>
| |
| | |
| system = script.Parent -- gets the Garage model
| |
| model = system.Car -- gets the Car model
| |
| backup = model:Clone() -- creates a copy of the Car model
| |
| regen = system.Regen -- Saves the integer value stored in the Garage's Regen variable
| |
| | |
| function checkRegen()
| |
| if regen.Value == 1 then -- When the player starts driving the car, the script
| |
| -- sets this value to 1
| |
| model = backup:Clone() -- copies the copy of the Car
| |
| model.Parent = system -- adds the plane to the Garage
| |
| model:MakeJoints()
| |
| end
| |
| end
| |
| | |
| regen.Changed:connect(checkRegen) -- When a Car is created, the regen value changes
| |
| -- from nil to a value - triggering this call.
| |
| | |
| </pre>
| |
| | |
| Your Explorer window should look something like this:
| |
| | |
| [[Image:CarGarage.PNG]]
| |
| | |
| === Creating the Car Model ===
| |
| | |
| The '''Car''' Model will hold all parts that are needed to make the car. Follow these steps to create the structure of the '''Car''':
| |
| | |
| *Select the '''CarGarage''' Model and insert an object Model. Name this new model '''Car'''.
| |
| *Select the '''Car''' model, and insert an object IntValue. Name this value '''Stunt'''.
| |
| *Insert into the '''Car''' model two additional models - name them '''Parts''' and '''BodyKit'''.
| |
| *The structure of the '''CarGarage''' model should now look like this:
| |
| | |
| [[Image:CarModel.PNG]]
| |
| | |
| === Creating the Parts Model ===
| |
| | |
| This model will hold all the key pieces that will make the car driveable. Follow these steps to add the necessary pieces:
| |
| | |
| *Select the '''Parts''' model and insert a CFrameValue object. Name this value '''OriginCFrame'''.
| |
| *Insert into the '''Parts''' model a script object. Name this script '''CarScript'''.
| |
| ::*Select the following code, copy it and paste it into the '''CarScript''' script:
| |
| | |
| <pre>
| |
| position = script.Parent.Engine.Position -- position of the engine
| |
| | |
| -- Add CFrame to Engine
| |
| local frame = Instance.new("CFrameValue")
| |
| frame.Name = "OriginCFrame"
| |
| frame.Value = script.Parent.Engine.CFrame
| |
| frame.Parent = script.Parent
| |
| | |
| -- Get the CarGarage
| |
| local object = Instance.new("ObjectValue")
| |
| object.Value = script.Parent.Parent.Parent
| |
| | |
| -- Get the Seat
| |
| seat = script.Parent.Seat
| |
| | |
| function onChildAdded(part)
| |
| -- if the user sits in the seat
| |
| if part.className == "Weld" then
| |
| local torso = part.Part1
| |
| if torso ~= nil then
| |
| local parent = torso.Parent
| |
| if parent ~= nil then
| |
| -- assign the CarGarage model to the player
| |
| script.Parent.Parent.Parent = parent
| |
| while true do
| |
| wait(2)
| |
| local pos = script.Parent.Engine.Position
| |
| -- once the car is far enough from original spot -
| |
| -- set the Regen value - so it causes another car to regenerate
| |
| if (position - pos).magnitude > 30 then
| |
| if object.Value ~= nil then
| |
| object.Value.Regen.Value = 1
| |
| wait(.5)
| |
| object.Value.Regen.Value = 0
| |
| object.Value = nil
| |
| end
| |
| break
| |
| end
| |
| end
| |
| while true do
| |
| wait(2)
| |
| if part == nil then
| |
| script.Parent.Parent.Parent = game.Workspace
| |
| script.Parent.Parent:MakeJoints()
| |
| break end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| -- When a player seats in the car
| |
| seat.ChildAdded:connect(onChildAdded)
| |
| | |
| | |
| </pre>
| |
| | |
| *Insert into the '''Parts''' model a Seat object. Note, this seat will be the driver's seat.
| |
| ::*Change the [[Size]] of the seat to be 2x2 (2 for x axis, and 2 for z axis.)
| |
| ::*Change the [[formFactor]] of the seat to be '''Plate'''.
| |
| ::*Change the [[BrickColor]] property to any color. In this example, the seat is Black.
| |
| ::*Change the FrontSurface property of the Seat to '''Hinge'''. This will show which side of the Seat is the front. It is important that the front of the Seat brick is facing the front of the car. The FrontSurface can be changed back to Smooth.
| |
| ::*To make sure the TopSurface is facing up, change it to be type '''Hinge'''. Make sure the yellow hinge is pointing up.
| |
| ::*Change the BottomSurface and TopSurface to Weld.
| |
| *Insert into the '''Parts''' model a Part object. Name it '''Engine'''.
| |
| ::*Change the [[Size]] of the '''Engine''' brick to be x=4, y=1.2, z=16. For this example, this brick will make the bottom of the car.
| |
| ::*Change the [[BrickColor]] property to any color. In this example, the '''Engine''' brick is Bright red.
| |
| ::*Change the FrontSurface property of the brick to '''Hinge'''. This will show which side of the brick is the front. It is important that the front of the Engine brick is facing the front of the car. The FrontSurface can be changed back to Smooth.
| |
| ::*Select the '''Engine''' brick, and insert into it the IntValue object. Rename the IntValue object to '''Count'''.
| |
| ::*Insert into the '''Engine''' brick a Script object. Copy and paste the following code into the '''Engine''' script object:
| |
| | |
| <pre>
| |
| model = script.Parent.Parent.Parent -- get the garage
| |
| backup = model:clone() -- copy it
| |
| local debounce = false
| |
| | |
| function onTouch(part)
| |
| if (part.Name == "Safe") and (debounce == false) and (script.Parent.Count.Value == 0) then
| |
| debounce = true
| |
| wait(2)
| |
| model = backup:clone()
| |
| model.Parent = game.Workspace
| |
| model:makeJoints()
| |
| script.Parent.Count.Value = 1
| |
| debounce = false
| |
| end
| |
| end
| |
| | |
| -- if Engine brick is touched
| |
| script.Parent.Touched:connect(onTouch)
| |
| </pre>
| |
| ::* Insert into the '''Engine''' brick a BodyGyro object.
| |
| :::*Set '''maxTorque''' values for x, y and z to 0.
| |
| ::* Insert into the '''Engine''' brick a BodyPosition object.
| |
| :::*Set '''maxForce''' values for x, y and z to 0.
| |
| ::* Insert into the '''Engine''' brick a BodyVelocity object, and name it '''Drift'''.
| |
| :::*Set '''maxForce''' values for x, y and z to 0.
| |
| :::*Set '''velocity''' values for x, y and z to 0.
| |
| *Insert into the '''Parts''' model an additional 4 Part objects. These bricks will become the wheels of the car. Name the 4 new bricks these names:
| |
| '''LeftWheel1''', '''LeftWheel2''', '''RightWheel1''', '''RightWheel2'''.
| |
| For each of these 4 wheel bricks, do the following:
| |
| ::*Make the BackSurface, BottomSurface, and TopSurface '''Smooth'''
| |
| ::*Make the [[Shape]] property '''Cylinder'''.
| |
| ::*Make the size (3,3,3)
| |
| ::*Make the [[formFactor]] property '''Symmetric'''.
| |
| ::*Set the [[BrickColor]] property to Black
| |
| | |
| At this point, you should have these pieces in your workspace:
| |
| | |
| [[Image:Parts2.PNG]]
| |
| | |
| === Assembling the Parts ===
| |
| | |
| Assemble these key pieces of the car as follows:
| |
| | |
| *Place the '''Seat''' on the front section of the '''Engine''' brick.
| |
| *Select the 4 wheels, and change the '''FrontSurface''' to '''Hinge'''. This will show you which is the front of the wheel.
| |
| *Place the wheels next to each side of the '''Engine''', where wheels go. Make sure the front surface of the wheel is facing to the front of the car.
| |
| *Make sure the Left wheels are on the left side of the car - On your left if you were sitting on the seat facing forward.
| |
| *Make sure the Right wheels are on the right side of the car.
| |
| | |
| *The wheels should look like this now:
| |
| [[Image:Wheels1.PNG]]
| |
| | |
| *Select the two left wheels, and change the '''RightSurface''' to be '''Motor'''.
| |
| *Select the two right wheels, and change the '''LeftSurface''' to be '''Motor'''.
| |
| *Now you need to move the '''Engine''' brick up a little, so the middle of the brick will align with the motor hinge of each wheel.
| |
| *NOTE: Since it can be difficult to move the wheels while they are inside the model, you may drag the wheels to be under the '''Workspace''' object in the Explorer window. This will allow you to move them with the move tool, to make sure they are attached properly to the engine brick. Once that is done, drag the wheels to be back under the '''Parts''' model.
| |
| *Make sure the hinges of the wheels (for the '''FrontSurface''') are pointing towards the front of the car.
| |
| *Move each wheel so that the motor hinge is inside the '''Engine''' brick.
| |
| *Change the '''FrontSurface''' to '''Smooth''' for each of the 4 wheels.
| |
| [[Image:Car1.PNG]]
| |
| | |
| === Adding the Car Tool ===
| |
| | |
| Follow these steps to add the Car Tool to players as they enter the game.
| |
| | |
| *Insert a [[HopperBin]] object under the [[StarterPack]] and name it '''Car Tool'''
| |
| *Select the '''Car Tool''' and insert a script object into it. Name the script '''CarDriver'''
| |
| *Copy the following code into the script.
| |
| | |
| <pre>
| |
| bin=script.Parent
| |
| car=nil | |
| hold=false
| |
| local debounce = false
| |
| local cardebounce = false
| |
| local stuntdebounce = false
| |
| local controlling = false
| |
| | |
| function computeDirection(vec)
| |
| local lenSquared = vec.magnitude * vec.magnitude
| |
| local invSqrt = 1 / math.sqrt(lenSquared)
| |
| return Vector3.new(vec.x * invSqrt, vec.y * invSqrt, vec.z * invSqrt)
| |
| end
| |
| | |
| function move(target, engine)
| |
| local origincframe = engine:findFirstChild("BodyGyro").cframe
| |
| local dir = (target - engine.Position).unit
| |
| local spawnPos = engine.Position
| |
| | |
| local pos = spawnPos + (dir * 1)
| |
| | |
| engine:findFirstChild("BodyGyro").maxTorque = Vector3.new(9000, 9000, 9000)
| |
| engine:findFirstChild("BodyGyro").cframe = CFrame.new(pos, pos + dir)
| |
| wait(0.1)
| |
| engine:findFirstChild("BodyGyro").maxTorque = Vector3.new(0, 0, 0)
| |
| engine:findFirstChild("BodyGyro").cframe = origincframe
| |
| end
| |
| | |
| function findCar(player)
| |
| local list = player.Character:GetChildren()
| |
| for x = 1, #list do
| |
| if (list[x].Name == "Car") then
| |
| local weld = list[x]:FindFirstChild("Parts"):FindFirstChild("Seat"):FindFirstChild("SeatWeld")
| |
| if (weld ~= nil) and (weld.Part1 == player.Character:FindFirstChild("Torso")) then
| |
| return list[x]
| |
| end
| |
| end
| |
| end
| |
| return nil
| |
| end
| |
| | |
| function onButton1Down(mouse)
| |
| local vehicle = findCar(script.Parent.Parent.Parent)
| |
| if vehicle ~= nil and debounce == false and cardebounce == false then
| |
| debounce = true
| |
| | |
| controlling = true
| |
| | |
| while true do
| |
| wait()
| |
| local engine = vehicle.Parts.Engine
| |
| local position = mouse.Hit
| |
| local target = position.p
| |
| if engine ~= nil then
| |
| move(target, engine)
| |
| end
| |
| if cardebounce == true or
| |
| controlling == false then break end
| |
| end
| |
| wait(.1)
| |
| debounce = false
| |
| end
| |
| end
| |
| | |
| function onButton1Up(mouse)
| |
| controlling = false
| |
| end
| |
| | |
| function onSelected(mouse)
| |
| mouse.Icon = "rbxasset://textures\\GunCursor.png"
| |
| mouse.Button1Down:connect(function() onButton1Down(mouse) end)
| |
| mouse.Button1Up:connect(function() onButton1Up(mouse) end)
| |
| mouse.KeyDown:connect(onKeyDown)
| |
| end
| |
| | |
| function onKeyDown(key)
| |
| if (key~=nil) then
| |
| key = key:lower()
| |
| local vehicle = findCar(script.Parent.Parent.Parent)
| |
| if (vehicle==nil) then return end
| |
| car = vehicle.Parts
| |
| local engine = vehicle.Parts.Engine
| |
| local r1 = engine.Parent.RightWheel1
| |
| local r2 = engine.Parent.RightWheel2
| |
| local l1 = engine.Parent.LeftWheel1
| |
| local l2 = engine.Parent.LeftWheel2
| |
| if (key=="x") and cardebounce == false then
| |
| r1.LeftParamB= 0
| |
| r2.LeftParamB= 0
| |
| l1.RightParamB= 0
| |
| l2.RightParamB= 0
| |
| end
| |
| if (key=="y") then
| |
| r1.LeftParamB= -1
| |
| r2.LeftParamB= -1
| |
| l1.RightParamB= 1
| |
| l2.RightParamB= 1
| |
| end
| |
| end
| |
| end
| |
| | |
| bin.Selected:connect(onSelected)
| |
| | |
| </pre>
| |
| | |
| === Testing your Car ===
| |
| | |
| The car frame is ready to be tested. Save your work and run it in either '''Test Solo''' mode, or ''Start Server'' and add a player to see if any error messages come up. The Car Tool has these commands:
| |
| * '''y''' will start the car. The car should start moving as soon as '''y''' is pressed.
| |
| * '''x''' will stop the car.
| |
| * Clicking the mouse will make the car turn in the direction of the click.
| |
| | |
| === Debugging Tips ===
| |
| *If the car doesn't move, but the mouse click makes it change direction, then you need to review every brick to make sure it is pointing forward (change the FrontSurface to hinge to verify).
| |
| *Verify the BodyGyro, BodyPosition and BodyVelocity objects in the engine have their values set to 0 - per the instructions.
| |
| *Verify the name of your model matches the instructions, or that you have changed the scripts accordingly.
| |
| | |
| === Creating the BodyKit Model ===
| |
| Now that the basic frame of the car is working, it can be completed to look as desired. Any additional bricks or parts should be added to the '''BodyKit''' model. The seat may be placed anywhere on the car, it does not have to sit on the engine brick. Here are some ideas for making the car look realistic:
| |
| *Add a floor and sides to the car
| |
| *Add a windshield using a mesh and a semitransparent brick
| |
| *Add more seats
| |
| *Add headlights and brake lights.
| |
| *Look through the free models for ideas on how to complete your car structure.
| |
| | |
| As the final shape of the car is developed, test the car by driving it - to ensure a change didn't break it.
| |
| | |
| | |
| [[image:BodyParts.PNG]]
| |
| | |
| [[Category:Scripting Tutorials]]
| |