How do I convert planes using BodyGyro and BodyVelocity to the new constraints?

Hello,

My group’s new game was just released. In it, we have planes, but right now there is only one plane that is used for transporting yourself and other players around the map.

It uses the old BodyMovers, which I know are depreciated, but I continued to use them since I was familiar with them + using the new constraints, was from my experience and the experience of other developers I know/work with, a PITA.

That being said, I have noticed that the BodyMovers don’t really work very well on my planes when there are multiple people in them. It can be glitchy. When there is a single person in the planes, they seem to work fine.

Anyway, I think it is time to convert my plane systems from BodyMovers to the constraint system, but I have no idea where to start… So I will describe how the planes fly + paste the code for it here.

Planes work when the player sits in the “pilot seat.” The network ownership of the “pilot seat” gets set to the player (and gets set to auto when the player leaves). Then, a local script is placed within the player, and this local script is used for controlling the plane’s movement, specifically responding to the player moving his or her mouse/cursor (or the player tapping on the screen on mobile), and orienting the plane based on that. There are no remotes involved for this. The local script has an ObjectValue in it that is used for connecting the physical plane model to the local script.

Here is the script that handles movement:

local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local Humanoid = char:WaitForChild("Humanoid")
local val = script:WaitForChild("plane")
local connection = val.Value
local USINS=game:getService("UserInputService")
local engine = connection:WaitForChild("Engine")
local gyro = engine:WaitForChild("BodyGyro")
local velo = engine:WaitForChild("BodyVelocity")
local clickMove = false

function GetBankAngle(M) --This function calculates the Bank Angle
	local VSX,X = M.ViewSizeX,M.X
	local Ratio = (((VSX/2) - X)/(VSX/2))
	Ratio = (Ratio < -1 and -1 or Ratio > 1 and 1 or Ratio)
	return math.rad(Ratio * 80)
end

if connection ~= nil then
	game["Run Service"].RenderStepped:Connect(function(step)		
		if velo.MaxForce == Vector3.new(math.huge,math.huge,math.huge) and not USINS:GetFocusedTextBox() then
			Mouse.TargetFilter = game.Workspace
			local BankAngle = GetBankAngle(Mouse)
			--gyro.maxTorque = Vector3.new(math.huge,math.huge,math.huge)
			--velo.maxForce = Vector3.new(math.huge,math.huge,math.huge)
			if clickMove then
				gyro.cframe = ((LastHit or Mouse.Hit)*CFrame.Angles(0,0,BankAngle))
			else
				gyro.cframe = (Mouse.Hit*CFrame.Angles(0,0,BankAngle))
			end
			velo.velocity = (engine.CFrame.lookVector)*values.currSpeed.Value
		end	
	end)
end
4 Likes

BodyVelocity can be replaced with LinearVelocity and BodyGyro can be replaced with AlignOrientation
Here’s how to replace the body movers:
Create an attachment inside of the engine part for the new constraints
then to replace BodyVelocity create a LinearVelocity inside of the engine part with the MaxForce set to the MaxForce you had on the BodyVelocity and then in the Script instead of changing BodyVelocity’s velocity change the LinearVelocity.VectorVelocity
To replace the BodyGyro create an AlignOrientation inside of the engine part with the MaxTorque set to the MaxTorque you had on the BodyGyro and then in the Script instead of changing BodyGyro.CFrame you need to change AlignOrientation.PrimaryAxis to the CFrame.RightVector and AlignOrientation.SecondaryAxis to the CFrame.UpVector
You can also make a function that changes AlignOrientation PrimaryAxis and SecondaryAxis properties to make it rotate to the CFrame’s rotation just like a body gyro

local function SetAlignOrientationCFrame(alignOrientation, cframe)
	alignOrientation.PrimaryAxis = cframe.RightVector
	alignOrientation.SecondaryAxis = cframe.UpVector
end

To change how fast the AlignOrientation rotates to the target rotation you can change the responsiveness property, higher responsiveness = faster, lower responsiveness = slower

3 Likes

What does the attachment’s orientation have to be though? Like how do I make sure that the attachment is point forward/the direction that the plane has to move in (aka how do I get the attachment to make sure it is following the LookVector property of the CFrame)?

1 Like

Just physically put an Attachment inside the engine part (not a script).
Try flying the airplane. If it flies sideways then rotate the vertical axis of the Attachment. If it rotates up and down instead of left/right then rotate the Attachment accordingly.
It has yellow and orange arrows to show the primary and secondary axes.

2 Likes

Continuing on,

I have attempted the conversion, and it has not gone well. The plane moves but is now uncontrollable, as seen in this GIF.

I am not really sure what I did wrong.

For the code, all I did was the following:

local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local Humanoid = char:WaitForChild("Humanoid")
local val = script:WaitForChild("plane")
local connection = val.Value
local USINS=game:getService("UserInputService")
local engine = connection:WaitForChild("Engine")
local gyro = engine:WaitForChild("AlignOrientation")
local velo = engine:WaitForChild("LinearVelocity")
local clickMove = false

local function GetBankAngle(M) --This function calculates the Bank Angle
	local VSX,X = M.ViewSizeX,M.X
	local Ratio = (((VSX/2) - X)/(VSX/2))
	Ratio = (Ratio < -1 and -1 or Ratio > 1 and 1 or Ratio)
	return math.rad(Ratio * 80)
end
local function SetAlignOrientationCFrame(alignOrientation, cframe)
	alignOrientation.PrimaryAxis = cframe.RightVector
	alignOrientation.SecondaryAxis = cframe.UpVector
end

if connection ~= nil then
	game["Run Service"].RenderStepped:Connect(function(step)		
		if not USINS:GetFocusedTextBox() then
			Mouse.TargetFilter = game.Workspace
			local BankAngle = GetBankAngle(Mouse)
			if clickMove then
				SetAlignOrientationCFrame(gyro,((LastHit or Mouse.Hit)*CFrame.Angles(0,0,BankAngle)))
			else
				SetAlignOrientationCFrame(gyro,(Mouse.Hit*CFrame.Angles(0,0,BankAngle)))
			end
			velo.VectorVelocity = (engine.CFrame.lookVector)*values.currSpeed.Value
		end
	end)
end

It appears that LinearVelocity works fine, but that using AlignPosition completely breaks it.
The following media show how I set up the constraints in the plane:
https://gyazo.com/52a9719abe6ab4b7f7984a775c9a3d6b
Close up of the Constraints
Close up of the AlignOrientation

I’ve been adjusting the different orientations of the Attachment, and all it does is make the plane flip out, like seen here.

Why do you have 2 Attachments at different Orientations at the nose of the aircraft? You should be able to just use a single one.
What are your AlignOrientation Properties? I’ve never used them for an airplane, but experiment with the settings of each Property to see how that reacts.

Actually, I saved a tutorial place that Roblox used to use to explain the differences of how the settings affect the parts. It doesn’t seem to be available anymore, but it shows how the settings affect what the part does in game.
New Body Movers, Physics, Constraints Example.rbxl (35.0 KB)

Also, planes don’t rotate around the nose, they generally rotate around their center of mass.

There are not two different Attachments at the nose of the aircraft. There is only one.

If you see other attachments, they are for other things like the propellers, firepoints for guns, etc.

So the nose AlignOrientation isn’t aligned. One yellow arrow is pointing forward and the other is pointing to the right.
What happens when you align both yellow arrows forward, or both right, or both pointing up?

And why the heck would you start another identical post?

The yellow arrow must be facing right and the orange arrow must be facing up