Troubles with Tweening welded model parts

  1. What do you want to achieve? Keep it simple and clear!

I have Bus model which can go from bus stop A to B. I need efficient script to make bus able of moving from bus stop to bus stop and opening its doors.

  1. What is the issue? Include screenshots / videos if possible!

I’ve tried welding the entire model together because tweening model with primary part is a really good solution. But that made it maybe? impossible to open doors since they have to be welded together with the model.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I’ve tried making sort of hierarchy system of welds in hopes it would work. I have most of the model welded to primary part and then I have parts of Door welded to primary part of Door which is welded to the primary part of model , sadly when I try to move the primary part of Door it still moves the entire model.
Then I’ve tried disabling the welds for the time of tweening but then doors would fall out of the bus.
I’ve tried to do it without welds, but the model has 250 parts which all would have to be tweened separately, which in higher bus amounts would make the game lag.
I tried looking in DevForums and asking AI, but it didn’t help. This is as far as I’ve gotten.

The bus uses 2 scripts, one inside the Bus Model and module script in replicated storage:
Module Script:

local BusFunctions = {}
local TS = game:GetService("TweenService")

function BusFunctions.MoveBus(BusPrimaryPart:Instance, Finnish:Instance, travelDuration:number)	
	print("Starting up motors")
	print(BusPrimaryPart.Name)
	local TweenI = TweenInfo.new(travelDuration, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
	local tween = TS:Create(BusPrimaryPart, TweenI, {["CFrame"] = Finnish.CFrame})
	tween:Play()
	tween.Completed:Wait()
	print("Bus arrived at crossroad/bus stop")
end
function BusFunctions.OpenAndCloseDoors(PrimaryPart:Instance,BackDoor:Model, DriverDoor:Model, DoorOpenedTime:number)
	local BDLeft = BackDoor.LeftDoor
	local BDRight = BackDoor.RightDoor
	local DDLeft = DriverDoor.LeftDoor
	local DDRight = DriverDoor.RightDoor
	local BDLeftCFrame = BDLeft.PrimaryPart.CFrame
	local BDRightCFrame = BDRight.PrimaryPart.CFrame
	local DDLeftCFrame = DDLeft.PrimaryPart.CFrame
	local DDRightCFrame = DDRight.PrimaryPart.CFrame
	local Ti = TweenInfo.new(3, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
	TS:Create(BDLeft.PrimaryPart, Ti, {["CFrame"] = (BDLeftCFrame - Vector3.new(0.668, 0, 0.845)) * CFrame.Angles(0, math.rad(90),0); ["Anchored"] = true}):Play()
	TS:Create(DDLeft.PrimaryPart, Ti, {["CFrame"] = (DDLeftCFrame - Vector3.new(0.668, 0, 0.845)) * CFrame.Angles(0, math.rad(90),0); ["Anchored"] = true}):Play()
	TS:Create(BDRight.PrimaryPart, Ti, {["CFrame"] = (BDRightCFrame - Vector3.new(-0.73, 0, 0.685)) * CFrame.Angles(0,math.rad(-90),0); ["Anchored"] = true}):Play()
	TS:Create(DDRight.PrimaryPart, Ti, {["CFrame"] = (DDRightCFrame - Vector3.new(-0.73, 0, 0.685)) * CFrame.Angles(0,math.rad(-90),0); ["Anchored"] = true}):Play()
	wait(3)
	print("Doors have been opened")
	wait(DoorOpenedTime)
	TS:Create(BDLeft.PrimaryPart, Ti, {["CFrame"] = BDLeftCFrame; ["Anchored"] = false}):Play()
	TS:Create(DDLeft.PrimaryPart, Ti, {["CFrame"] = DDLeftCFrame; ["Anchored"] = false}):Play()
	TS:Create(BDRight.PrimaryPart, Ti, {["CFrame"] = BDRightCFrame; ["Anchored"] = false}):Play()
	TS:Create(DDRight.PrimaryPart, Ti, {["CFrame"] = DDRightCFrame; ["Anchored"] = false}):Play()
	wait(3)
	print("Doors have been closed")
end
return BusFunctions -- I had troubles with making both things happen at least, that's why there's Anchored variables inside the tween goals

Script inside Bus Model:

local BusFunctions = require(game.ReplicatedStorage.BusFunctions)
local BusStopWaitTime = 30 -- in seconds
local TS = game:GetService("TweenService")
local DoorsFolder = script.Parent.Doors
local BackDoor = DoorsFolder.BackDoor
local DriverDoor = DoorsFolder.DriverDoor
BusFunctions.OpenAndCloseDoors(script.Parent.PrimaryPart, BackDoor, DriverDoor, 5)
wait(2)
BusFunctions.MoveBus(script.Parent.PrimaryPart, game.Workspace.Finish, 10)

Does anyone know how to make this work with welds? Or any other reasonable solution?

Unweld the doors when they have arrived, or make the doors one mesh and the bus also one mesh, weld them together and unweld the doors when you arrived, you can also play around with lerping, but I think tweening is a better option for this scenario.

How do I make from the Doors mesh?
The bus has 2 doors, one at front and one at back so it would be 3 meshes but still. The doors mesh would just fall out of the right placement, or bump into the bus which would make the bus move.

Welds (not WeldConstraint) have properties named C0 and C1, these can be modified to allow you to offset the individual positioning of a part without affecting the rest of the model (like the Bus in this case). I would mess around with it in studio to see what values work in opening the doors using the weld of the door’s C0 and C1, and then do it in your script with tweening.

You could tween the C0 of the door welds rather than the cframes of the doors themselves. If you do this, dont forget to use :ToObjectSpace() since C0s are relative offsets of the Part0, rather than absolute worldpositions.

  1. create a CFrameValue instance
  2. connect a function to .Changed on the CFrameValue that calls :PivotTo() (or your other favorite model-moving function)
  3. tween the CFrameValue and delete it when your tween is no longer needed

should end up looking somethin’ like:

local CFrameHolder = Instance.new("CFrameValue") -- doesn't need a parent
CFrameHolder.Changed:Connect(function()
	BusModel:PivotTo(CFrameHolder.Value)
end)
local BusTween = TweenService:Create(CFrameHolder, TweenInfo.new(), {Value = TargetCFrame})
BusTween.Completed:Connect(function()
	CFrameHolder:Destroy()
end)
BusTween:Play()

i think the garbage collector takes care of any instances/connections there

alternatively, you could always make a custom tween but uhh, u should be able to find resources on that

1 Like