Bodyvelocity train sometimes shaking when moving

robloxapp-20240722-1322078.wmv (2.2 MB)
How to fix it? (the train has a lot of weight)

2 Likes


BodyVelocity properties

nice work btw i’ve wanted to make a train driving game my whole life but couldn’t srry i couldn’t help

2 Likes

Well if we could see the script that would be nice, also maybe lower maxforce then I guess.

2 Likes

Sure!

local dir = 1
local maxspeed = 120
local currentspeed = 0
local num = 0
local tw = game:GetService("TweenService")
local DL = false
local DR = false
local runservice = game:GetService("RunService")
local soundmodule = require(script.Parent.SoundScript)

local speedtable = {

	0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
	10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
	20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
	30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
	40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
	60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
	70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
	80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
	90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
	100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
	110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
	120}
function playsound(name)
	for i,k in pairs(script.Parent.Parent.Parent:GetDescendants()) do
		if k:IsA("Sound") then
			if k.Name == name then
				
				k:Play()
			end
		end
	end
end

function getMass(model)	
	local mass = 0;
	for i,v in pairs(model:GetDescendants()) do
		if(v:IsA("BasePart")) then
			mass += v:GetMass();
		end
	end
	return mass;
end

function settupBV()
	for i,k in pairs(script.Parent:GetDescendants()) do
		if k:IsA("BodyVelocity") then
			k.MaxForce = Vector3.new(9230150,0,9230150)
		end
	end
end

function opendoors(side)
	if side == "L" then
		for i,q in pairs(script.Parent.Parent.Parent:GetDescendants()) do
			if q.Name == "DLeft" then
				for i,a in pairs(q:GetDescendants()) do
					if a.Name == "DoorLock" then
						a.Enabled = false
					end
					if a.Name == "DoorMotor" then
						if a:IsA("PrismaticConstraint") then

							a.Speed = math.random(2,4)
							tw:Create(a,TweenInfo.new(2,Enum.EasingStyle.Elastic),{TargetPosition = math.random(2,2.1)}):Play()

						end
					end
				end
			end
		end
	end
	if side == "R" then
		for i,q in pairs(script.Parent.Parent.Parent:GetDescendants()) do
			if q.Name == "DRight" then
				for i,a in pairs(q:GetDescendants()) do
					if a.Name == "DoorLock" then
						a.Enabled = false
					end
					if a.Name == "DoorMotor" then
						if a:IsA("PrismaticConstraint") then

							a.Speed = math.random(2,4)
							tw:Create(a,TweenInfo.new(2,Enum.EasingStyle.Elastic),{TargetPosition = math.random(2,2.1)}):Play()

						end
					end
				end
			end
		end
	end
end


function closedoors(side)
	if side == "L" then
		for i,q in pairs(script.Parent.Parent.Parent:GetDescendants()) do

			if q.Name == "DLeft" then
				for i,k in pairs(q:GetDescendants()) do
					coroutine.wrap(function()
						if k:IsA("PrismaticConstraint") then
							k.Speed = math.random(2,4)
							k.TargetPosition = 0.6
							wait(0.3)
							tw:Create(k,TweenInfo.new(1,Enum.EasingStyle.Bounce),{TargetPosition = -0.04}):Play()
							wait(1)
							k.Speed = 0
							for i,a in pairs(q:GetDescendants()) do
								if a.Name == "DoorLock" then
									if a:IsA("SpringConstraint") then
										if k.TargetPosition <= 0 then
											a.Enabled = true
										end
									end
								end
							end
						end
					end)()
				end

			end


		end
	end
	if side == "R" then
		for i,q in pairs(script.Parent.Parent.Parent:GetDescendants()) do

			if q.Name == "DRight" then
				for i,k in pairs(q:GetDescendants()) do
					coroutine.wrap(function()
						if k:IsA("PrismaticConstraint") then
							k.Speed = math.random(2,4)
							k.TargetPosition = 0.6
							wait(0.3)
							tw:Create(k,TweenInfo.new(1,Enum.EasingStyle.Bounce),{TargetPosition = -0.04}):Play()
							wait(1)
							k.Speed = 0
							for i,a in pairs(q:GetDescendants()) do
								if a.Name == "DoorLock" then
									if a:IsA("SpringConstraint") then
										if k.TargetPosition <= 0 then
											a.Enabled = true
										end
									end
								end
							end
						end
					end)()
				end
			end


		end
	end
end


script.RemoteEvent.OnServerEvent:Connect(function(plr,data,data2)
	if data == "thr" then
		if data2 == 5 then
			num = 0.3

		end
		if data2 == 4 then
			num = 0.25

		end
		if data2 == 3 then
			num = 0.2

		end
		if data2 == 2 then
			num = 0.15
			
		end
		if data2 == 1 then
			num = 0.1
			
		end
		if data2 == 0 then
			num = 0
			
		end
		if data2 == -1 then
			num = -0.25
			
			
		end
		if data2 == -2 then
			num = -0.35
			
		end
		if data2 == -3 then
			num = -0.35

		end
		if data2 == -4 then
			num = -0.45

		end
		if data2 == -5 then
			num = -0.5

		end
	end
	if data2 == "L" then
		if data == "Door" then

			if DL == false then
				DL = true
				playsound("doors")
				wait(0.5)
				opendoors("L")
			else
				DL = false
				playsound("doors")
				wait(0.5)
				closedoors("L")
			end


		end

	end
	if data2 == "R" then
		if data == "Door" then

			if DR == false then
				DR = true
				playsound("doors")
				wait(0.5)
				opendoors("R")
			else
				DR = false
				playsound("doors")
				wait(0.5)
				closedoors("R")
			end


		end

	end
end)

settupBV()

while wait(0.1) do
	
print(num)
	script.currentspeed.Value = currentspeed
	script.num.Value = num
	if num > 0 or num == 0 then
		currentspeed += num
		end
	if currentspeed > maxspeed then
		currentspeed = maxspeed
	end
	if currentspeed < 0 then
		currentspeed = 0
	end
	for i,q in pairs(script.Parent.Parent.Parent:GetDescendants()) do
		if q:IsA("BodyVelocity") then
			q.Velocity = q.Parent.CFrame.LookVector * dir * currentspeed
		end
	end
	for i,k in pairs(script.Parent.Parent.Parent:GetDescendants()) do
		
		if k:IsA("Sound") then
			if k.Name == "Depart" then
				if k.Volume == 0  then
					k.Playing = false
				end
				if currentspeed > maxspeed - 5 then
					k.Volume = 0
				else
					if num > 0 and num ~= 0 then
						k.Playing = true
						tw:Create(k,TweenInfo.new(15),{Volume = 10}):Play()
					end
				end
				tw:Create(k,TweenInfo.new(4),{PlaybackSpeed = 1 + num}):Play()
				if num > 0 and num ~= 0 then
					k.Playing = true
					tw:Create(k,TweenInfo.new(15),{Volume = 10}):Play()
				else
					tw:Create(k,TweenInfo.new(0.3),{Volume = 0}):Play()
				
				end
				k.PlaybackRegion = NumberRange.new(currentspeed / (120/k.TimeLength),currentspeed / (120/k.TimeLength)+10)

			end
			if k.Name == "Arrive" then
				if k.Volume == 0  then
					k.Playing = false
				end
				tw:Create(k,TweenInfo.new(4),{PlaybackSpeed = 1 + -num/5}):Play()
				if num < 0 and num ~= 0 then
					k.Playing = true
					if k.TimePosition > 0 then
						if num < 0 and num ~= 0 then
							if currentspeed ~= 0 then
								currentspeed -= 0.1
							end
						
						end
					end
					if k.TimePosition > 5 then
						if num < 0 and num ~= 0 then 
							if currentspeed ~= 0 then
							currentspeed -= 0.2
							end
						end
					end
					if k.TimePosition > 40 then
						if num < 0 and num ~= 0 then 
								if currentspeed ~= 0 then
						
							currentspeed -= 0.5
							end
						end
					end
					tw:Create(k,TweenInfo.new(7),{Volume = 10}):Play()
				else
					tw:Create(k,TweenInfo.new(0.3),{Volume = 0}):Play()

				end
				if currentspeed > 1 then
				k.PlaybackRegion = NumberRange.new(((currentspeed / (120/k.TimeLength)) - k.TimeLength) * -1,k.TimeLength)
end
				   if currentspeed < 2 then
						k.Volume = 0
						
				   end
			end
						if k.Name == "Run" then
		   k.Volume = currentspeed / (70/10)
		   k.PlaybackSpeed = currentspeed / (90/1.5)
			end
			
		
	
	end
	
	end
     
	
end

You’re using spring constraints, and prismatic constraints? Why don’t you just use the prismatics for the sliding of the train along the tracks then? Instead of using bodyvelocity, and i’m not sure why you are using spring constraints because that’s only really for the bumping effect of cars.

I’m pretty sure the spring constraint is the problem as it’s causing that shake effect, but you may also wanna play around with network ownership.

1 Like

I use Prismatic for doors and Spring for locks

And these are within the train?

Honestly, I recommend just lerping the CFrames. Roblox physics can be buggy like this and is not reliable for huge baseparts like this train.

You will also have more control, and unlike roblox physics where the train can sometimes spaz out like right now. The train will remain functional.

1 Like

Okay i will try, i will reply later

How i will lerp the train lookvector?

Alright, it could also be due to that while loop. The little “task.wait(0.1)” can make it a bit suttery, try just using “task.wait()”

1 Like

You might not need to use the lookvector, just CFrames since they represent both orientation and position.

Lookvectors would’ve been needed for that bodyvelocity thing you were doing, but not now.

okay, what about alpha, how to use it?

Alpha is like, how far you want it to be. Kinda hard to explain. Let me show a code sample.

for i = 0, 1, .01 do
Train.CFrame = Train.CFrame:Lerp(Train.CFrame * CFrame.new(0,0,1), i)
end

Think of the number 0 and 1 like point A and B.

Number 0 is point A, you are at the starting position and haven’t travelled to point B at all yet.

By 0.5 your halfway

By 1, you’ve made it to point B.

The little incrementing on that for loop (0.01) will make a smoother transition

how to convert cframe to vector3 bc bodyvelocity support vector3?

You can do that by just doing CFrame.Position, but this wouldn’t work in the way you want it to because it would not represent the orientation either. Which may be a problem if your train is not just a straight path and has turns or what not.

Also you might not need to lerp at all, maybe just setting the CFrames is enough.

Train.CFrame = Train.CFrame * CFrame.new(0,0,1)

Just asking is it possible to lerp bodyvelocity?

I’m just not very good at writing scripts, how can this problem be solved? you gave me a bunch of different options for train animation, how can I apply this in my game?