Tweening in order

I am in the midsts of making a roblox monorial/minecart system, now I do not intend to use it in a normal way everyone else would.

I am trying to loop through every part parented to a track in order of the name of the part e.g… 1,2,3,4,5,6 but my part just tweens to the end block and not the ones infront.

local uis = game:GetService("TweenService")

tis = TweenInfo.new(
15
)

local start = function()
for i,v in pairs(workspace.Track:GetChildren()) do
uis:Create(script.Parent, tis, {CFrame = v.CFrame}):Play()
end
end

start()

Would someone like to tell me how I can accomplish this, I am more than likely going for a stupid approach.

Cheers.

1 Like

Tween:Play() won’t yield until the tween is finished. This means the first four tweens are cancelled prematurely because the for loop continues to iterate through each child and overlap the same logic on the same part (this will cancel previous tweens before they have completed). This is where the Tween.Completed event comes in handy. You can yield until the event is fired, ensuring each tween is completed before iterating to the next instance.

Using your implementation:

local TweenService = game:GetService("TweenService") -- appropriate convention is to declare services exactly as they are in the datamodel.

Info = TweenInfo.new(
    15
)

function start()
    for i,v in pairs(workspace.Track:GetChildren()) do
        local tween = TweenService:Create(script.Parent, Info, {CFrame = v.CFrame})
        tween:Play()
        tween.Completed:Wait() -- yields until the tween is completed.
    end
end

start()
1 Like

Uh, a file wont upload so.

The part slows down if the parts are closer together, I know this is because of the tween time it takes to get across to the other one, do you suggest other ways of making this?

Specifying the EasingStyle as Linear will ensure that the tweened instance moves at a consistent rate.

Adding it into your implementation:

local TweenService = game:GetService("TweenService") -- appropriate convention is to declare services exactly as they are in the datamodel.

Info = TweenInfo.new(
    15,
    Enum.EasingStyle.Linear
)

function start()
    for i,v in pairs(workspace.Track:GetChildren()) do
        local tween = TweenService:Create(script.Parent, Info, {CFrame = v.CFrame})
        tween:Play()
        tween.Completed:Wait() -- yields until the tween is completed.
    end
end

start()

It didnt work, it still bounces between speeds.

The linear EasingStyle ensures that the instance moves at a constant speed instead of fast at the beginning of the tween and slow at the end. If you’re talking about different speeds based on different node distances, then that is an issue you will have to manually solve by calculating the time based on distance. Naturally the further an object, the longer it would take to reach.

I whipped up a quick example which calculates the tween time by finding the magnitude between the node and instance, then multiplying it by a pre-set seconds-to-stud constant. It moves at a constant speed between different nodes (E.g. If a node is 20 studs away, it takes 2 seconds to reach it. If a node is 50 studs away, it takes 5 seconds to reach it).

local TweenService = game:GetService("TweenService") -- appropriate convention is to declare services exactly as they are in the datamodel.

local SecondsPerStud = 0.1

function start()
    for _,v in pairs(workspace.Folder:GetChildren()) do
        local Info = TweenInfo.new(
   	    (v.Position - script.Parent.Position).Magnitude * SecondsPerStud,
            Enum.EasingStyle.Linear
        )
        local tween = TweenService:Create(script.Parent, Info, {CFrame = v.CFrame})
        tween:Play()
        tween.Completed:Wait() -- yields until the tween is completed.
    end
end

start()

Is this the behaviour you wanted?

2 Likes