Invert BodyVelocity Z axis when a is in a certain orientation

Hello! Today I need help to make an airplane system.

  1. I don’t want to use free models
  2. I made a script to let it fly but if I turn it it will keep going forward but in reverse
  3. I’m using BodyVelocity to move it

This is how it works now:

I think that you can see from the video what I’m trying to achieve.

In the video the airplane starts in the Z positive axis when I want to return to the baseplate is continue to go ahead and not to the baseplate.

The seat is in a wrong orientation but the start direction is correct.

Any help is welcome!

Could we see the script? You probably mess something up along your lines of changing the Velocity property

local seat = script.Parent
local body = seat.Parent.Body

local function createVelocities()
	local forwardV = Instance.new("BodyVelocity", body)
	forwardV.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
	forwardV.Velocity = Vector3.new(0, 0, 30)
	
	local steerV = Instance.new("BodyAngularVelocity", body)
	steerV.AngularVelocity = Vector3.new(0, 0, 0)
	
	local throttleV = Instance.new("BodyAngularVelocity", body)
	throttleV.AngularVelocity = Vector3.new(0, 0, 0)
end

body.ChildAdded:Connect(function()
	--forwardV = body:FindFirstChild("BodyVelocity")
	steerV = body:FindFirstChild("BodyAngularVelocity")
	throttleV = body:FindFirstChild("BodyAngularVelocity")
end)

local function destroyVelocities()
	for i, v in pairs(body:GetChildren()) do
		if v:IsA("BodyVelocity") or v:IsA("BodyAngularVelocity") then
			v:Destroy()
		end
	end
end

local function steerR()
	steerV.AngularVelocity = Vector3.new(0, -5, 0)
end

local function steerL()
	steerV.AngularVelocity = Vector3.new(0, 5, 0)
end

local function idleSteer()
	steerV.AngularVelocity = Vector3.new(0, 0, 0)
end

local function throttleUp()
	throttleV.AngularVelocity = Vector3.new(-5, 0, 0)
end

local function throttleDown()
	throttleV.AngularVelocity = Vector3.new(5, 0, 0)
end

local function throttleStop()
	throttleV.AngularVelocity = Vector3.new(0, 0, 0)
end

seat.Changed:Connect(function(property)
	if property == "Occupant" then
		if seat.Occupant ~= nil then
			createVelocities()
		else
			destroyVelocities()
		end
	end
	if property == "Steer" then
		if seat.Steer == 1 then
			steerR()
		elseif seat.Steer == -1 then
			steerL()
		else
			idleSteer()
		end
	end
	if property == "Throttle" then
		if seat.Throttle == 1 then
			throttleUp()
		elseif seat.Throttle == -1 then
			throttleDown()
		else
			throttleStop()
		end
	end
end)

This script doesen’t have the invert velocity because i remowed it :confused:

This is the script that let it just fly forward.

In my opinion I recommend that you use vector forces and Torque instead.
I do use bodyVelocity sometimes however when it comes to physics I do not trust it anymore.

I feel they they are a lot less performant that forces and it is possible to put multiple forces acting on one assembly.

However, if you still want to use body Velocity I think the problem is that it is always aligned or relative to the world. so you would have to calculate the velocity. If you do not know. velocity is a direction and a speed. Since direction is relative to the world if you want to change direction you have to change the velocity relative to the world.

These are some examples of how Vectors are created on a 2d plane. Velocity is a Vector. So you would have to create your own vectors.

There is some maths that you can use to calculate this.(Although you don’t have to)

Of course. It will have to be updated every frame if you would like to achieve a smooth turning

TLDR
Velocity is relative to the world if you want to change direction you have to change the velocity.

To find out the direction you could do . CFrame.lookVector to get the direction and multiply by speed to get the speed that you want.

Sorry can you plase do an example? I want to move the airplane basing on the orientation.

I don’t know how to create my own vectors.

I am very sorry it took so long to reply. I manged to make a quick rblx file you can look into.
Here is the code for the Model.

--References for instances
local Body = script.Parent
local Model = Body.Parent
local VehicleSeat = script.Parent.Parent.VehicleSeat

--Reference for services
local RunService = game:GetService("RunService")

--Reference for new instances
local BodyVelocity = Instance.new("BodyVelocity",Body)
BodyVelocity.MaxForce = Vector3.new('inf','inf','inf')									-- Here are just setting up the Body Velocity Properties
BodyVelocity.P = 2000
BodyVelocity.Velocity = Vector3.new(0,0,0)

local BodyGyro = Instance.new("BodyGyro",Body)   
BodyGyro.P = 5000 																		-- Here are just setting up the Body Gyro Properties
BodyGyro.D = 1000
BodyGyro.MaxTorque = Vector3.new('inf','inf','inf')		

local Direction = Body.CFrame.LookVector 												-- Forward direction
local Speed = VehicleSeat.MaxSpeed 														-- Speed of the system
local Velocity = Vector3.new()


local TargetDirection = BodyGyro.CFrame * CFrame.Angles(0,0,0)							-- This is my method of how to turn
local TurningSpeed = VehicleSeat.TurnSpeed

RunService.Stepped:Connect(function(time,deltaTime)

    BodyGyro.CFrame = BodyGyro.CFrame * CFrame.Angles(0,math.rad(TurningSpeed * -VehicleSeat.SteerFloat),0)	-- Again this is my method of turning you can use yours 

    Direction = Body.CFrame.LookVector
    Velocity = VehicleSeat.ThrottleFloat * Direction * Speed							-- Here we get the input of the player, the direction of the assembly and the speed you want them to go.
    BodyVelocity.Velocity = Velocity

end)

PlaneBodyMovers.rbxl (32.2 KB)
Hopefully this helped :smiley: :wave:

Yes it helped a bit. But this is my first time that i use bodyvelocity, bodygyro, and i need that the plane goes always forward and never back ultil the player leaves it; in your script I don’t understand how you detect what key is pressed like W or A or D and how i can make it always going forward. Can you please explain?

Oh I see.

I am quite a lazy person so usually I look in Roblox API for already existing functions instead of programming them myself.
One thing I found out is that there is a property called “ThrottleFloat” and “StearingFloat” in the VehicleSeat. I recommend you don’t use this because there are only 4 possible movements:
Forward. Back and Left, Right. They Update based on the player’s input and they return a number. I simply got those and plugged it into the equation(since it is a number) and voila!

Read this for more info and look under ThrottleFloat and SteerFloat.
VehicleSeat | Roblox Creator Documentation
and if you want to look even more into it
VehicleController | Roblox Creator Documentation

If you want to make custom controller for your vehicle (which you will need to do if you are going to make a plane)
You should use ContextActionService | Roblox Creator Documentation to get player input.
Use Bindable Events and Functions | Roblox Creator Documentation to pass player input to the server.

Now when you have got all the inputs on the server this is when the problem solving aspect comes into it.

If you want to make the Velocity go forward even after you let go simply remove the input from the equation. Then the plane would move forward no matter what.

-- Instead of
Velocity = VehicleSeat.ThrottleFloat * Direction * Speed
-- Do
Velocity =  Direction * Speed

If you want to have the throttle “toggled” simply make a variable.

When the player presses W the VehicleSeat.ThrottleFloat is 1 when the player presses S the VehicleSeat.ThrottleFloat is -1 so:

local Throttle = 0--Variable to control whether or not the plane should be moving.

Now in the RunService.Stepped function we can instead do

if VehicleSeat.ThrottleFloat > 0 then
    Throttle = 1 --Substitute for true if you want to 
elseif VehicleSeat.ThrottleFloat < 0 then
    Throttle = 0 --Substitube for false if you would like to
end
Velocity = Throttle * Direction * Speed

Is using seat.Steer/seat.Throttle the same of using contexaction?

No. Not at all. Sorry for late reply again.

Context action service is a service that is used to get player input whilst something is happening. For example you can choose to get player input when he/she has reached a new position or if he/she is sitting on a seat etc.

On the other hand VehicleSeat.Steer and VehicleSeat.Throttle are properties from a vehicle seat that are changed based on the user input.

Technically they do the same thing, get user input, however one is much more limited in scope and in what it is able to do.

You can use the context action service when the player sits in a seat. When the player is in the seat check for the seat and if the seat is the correct seat you can bind the function to fire the remoteEvent which will change the Velocity of the plane.

If you do not know how Context action service works I recommend you try and experiment with less complex procedures using UserInputService | Roblox Creator Documentation first if you haven’t already. for example when you press a key on your keyboard the Baseplate changes colour. or something like that.

The reason being is because it is usually better to make less complex stuff before tackling something complicated if you are new.

TLDR
Try to learn input by using User Input Service first. Once you get the hang of it @ me and I will carry on guiding you through the process.

First of all thank you for your patience and availability, no matter the time for the reply. I have some issues:

  1. I will have multiple airplanes and if i use remoteevents the scripts will run for every airplane,
  2. I don’t understand how i can manage the inputs, i would prefer to use UserInputService since i can check them for mobile too instead of ContextActionService that will create buttons on the screen of the mobile players and since i need some buttons their screen will be full of buttons,
  3. I don’t understand how to move the body in the correct direction. :weary:

@koziahss thank you for all of your help, it is really apprecciated, thank you for all of your suggestions also for let me know of contextactionservice (thing of i wasn’t aware)! The problem is solved! I just didn’t understand how to use the velocity, I solved it setting the bodyvelocity as this: velocity = body.CFrame.lookVector * 30.

Ah.

  1. Well first of all when it comes to remote events you can pass in more than just the input. You can also pass through the plane, input, player who controls the plane and you could also pass in more input for example lights that are on the plane.

It is very easy to forget that remote events are simply a way of communication between the player and the server

The player knows what seat he/she is sitting it.
The player can talk to the server
Therefore you can tell the server what seat the player is sitting in.
The server can use the seat to know which plane to move.
The server can change the properties which would be then replicated to all other clients.

Once you get more experience with programming you will also get more experience with Roblox’s API and be able to solve more complicated things in the future :slight_smile: Carry on !

2 USE BOTH! You don’t have to be picky about what services to use you can use whatever services feels right when you need it. I am sure there is a way to handle mobile devices however I would say for the first few weeks programming do not worry too much about making your games completely mobile friendly. Most games take a long time before they turn into mobile friendly ones.

That being said, it isn’t too much harm learning about it early on.

Just for clarity
Context Action Service is used when the player is in a specific state e.g. Equip a tool or sit in a seat or is swimming etc.

User Input Service is used for getting user input generally. These are more used usually through out the game and handle the functions that are constant e.g. Opening Shop Gui, Settings etc.

There are a bunch of things that they do that are unique to them
UIS can get VR input and device rotation also can get pointer location.

CAS can make mobile friendly onscreen buttons for the user can be set to enable on the equip of a tool and can be disabled and enabled very easily.

Most cases you should use CAS since it can be unbound. In your case CAS would be the best option to go with. If you still don’t understand how you can solve this just reply.

  1. This one might be a bit harder to explain. I think I should use pics
    lets start from 2d first

What is a vector?

[1,2] <----This is a vector sometimes it is drawn from top to bottom.

Vectors can describe a Position Direction or Velocity
Vector1,1
This here is a vector [1,1]
We are starting in 2d bc it is much easier to understand

Magnitude

The magnitude of a vector is the length of the line. You might even be able to work it out how long the line even is using a calculator.

If you took maths you may know that a^2 + b^2 = c^2 – Trigonometry

Thankfully we do not have to do this in Roblox

A quick look on Vector3 You might be able to see a property called Magnitude.Very convenient :smiley:

Okay next

Direction

You might be able to see that this vector is pointing in a different way
Now do you think the Vector for this will be? (A>C)
Vector-2,1
Click below to see the answer.

[-2,-1]

If you managed to get this right !!WELL DONE!! :smiley: :partying_face: :partying_face:
If not that’s okay we all learn at different rates…

You might also be start to realize how changing a vector changes it’s direction.
A Unit Vector is what is used commonly to describe a direction. A unit vectors length is always 1

If you look at CFrame You may be able to see a property called lookVector Which is actually a unit vector which means we can use it for direction. Pretty handy!

Velocity

Now let’s say we have 2 Velocities

[3,3]
[5,1]

Which one do you think is faster?

At first you may think they are both the same however look at it on a graph.

Vectors

The faster Vector is actually [5,1] !
The speed of the vector is actually the length of the Vector so Magnitude == Speed!

Once you start looking into Vectors more and using them more you should be able to understand them better.

I just read your post but I already wrote this so…Ah well. Ping me if you need me!

2 Likes