Tweening to a moving target

Hello, and welcome to this tutorial on tweening to a moving part.

Have you ever wanted to animate something going from one part to another, but the goal is
moving? Simply using TweenService will only go to a static goal. If you repeatedly try to
tween something to a moving goal, it would work, but you wouldn’t be able to use easing
styles properly.

For this example we will be tweening pieces of scrap to a moving magnet.

Step 1: Setting up the module
We will make a ModuleScript in ServerStorage. Name it “Tweening” or something you think
fits for your game.

Step 2: Write the module code
First, we need to make something happen when we require the module. This will be the
base of our code, which includes the services we need.

local ts = game:GetService("TweenService")
local rs = game:GetService("RunService")
return function(part,targetpoint,tweeninfo)
end

At the start of our function, we can add some variables that will come in handy later.

local startingpoint = part.Position
local startingrotation = part.Orientation
local weight = Instance.new("NumberValue")

Next, we will have our code that sets the parts position. How this works is the starting
position will start with a multiplier of 1, and the ending (moving) position will start with a
multiplier of 0. When we change the weight later, the part we are moving will be somewhere
between those two positions. When the weight gets to 1, the part will be at it’s goal.

local step = rs.Stepped:Connect(function()
part.Position = startingpoint*(1-weight.Value)+targetpart.Position*weight.Value
part.Orientation = startingrotation*(1-weight.Value)+targetpart.Orientation*weight.Value
end)

Now we can tween the weight. The top line just sets a default TweenInfo if there isn’t one
specified.

local tweeninfo = tweeninfo or TweenInfo.new()
local tween = ts:Create(weight,tweeninfo,{Value = 1})
tween:Play()
tween.Completed:Wait()

We need to decide what our code will do when we finish the tween. In this example, we will disconnect the stepped function and weld our part to the target part.

step:Disconnect()
local weld = Instance.new("ManualWeld")
weld.Part0 = part
weld.Part1 = targetpart
weld.Parent = part
part.Anchored = false

Here is our entire module:

local ts = game:GetService("TweenService")
local rs = game:GetService("RunService")
return function(part,targetpart,tweeninfo)

local startingpoint = part.Position
local startingrotation = part.Orientation
local weight = Instance.new("NumberValue")

local step = rs.Stepped:Connect(function()
part.Position = startingpoint*(1-weight.Value)+targetpart.Position*weight.Value
part.Orientation = startingrotation*(1-weight.Value)+targetpart.Orientation*weight.Value
end)

local tweeninfo = tweeninfo or TweenInfo.new()
local tween = ts:Create(weight,tweeninfo,{Value = 1})
tween:Play()
tween.Completed:Wait()

step:Disconnect()
local weld = Instance.new("ManualWeld")
weld.Part0 = part
weld.Part1 = targetpart
weld.Parent = part
part.Anchored = false

end

Step 3: Using the module
So we have our module set up, let’s use it!

You can use the module like this:

local module = require(game.ServerStorage.Tweening)
module(movingpart,targetpart,tweeninfo)

Here is my giant magnet, it has an invisible part under it which I will be using for the base. The stripy part is welded on top.

image

Now we can tween the base over a bunch of trash. I will also have it pick up all the pieces of trash using our module when they’re nearby. All trash pieces are in a Folder named “Trash”.

local ts = game.TweenService
local base = script.Parent.Base
local module = require(game.ServerStorage.Tweening)
local trash = workspace.Trash:GetChildren()
local pickedup = {}

base:GetPropertyChangedSignal("CFrame"):Connect(function()
for i,trash in pairs(trash) do
if (trash.Position-base.Position).Magnitude<20 and not table.find(pickedup,trash) then
table.insert(pickedup,trash)
module(trash,base,TweenInfo.new(.5,Enum.EasingStyle.Bounce,Enum.EasingDirection.Out))
end
end
end)

ts:Create(base,TweenInfo.new(1,Enum.EasingStyle.Linear),{CFrame = base.CFrame+Vector3.new(150,0,0)}):Play()

Here is the result:

Get the place with the module here: DevTutorial.rbxl (25.3 KB)

You can easily make this a module for the client by changing .Stepped functions to .RenderStepped functions. This method of tweening isn’t limited to just positions. You can tween a lot of different values like this. You could tween a colour to a changing colour if you wanted.

Thanks for reading!

38 Likes

Idk if anyone else found this Useful but it really was for me, TYSM!

https://gyazo.com/87eb4e2a91021c7fafe9e951337e8a0b

2 Likes

This is a really helpful script, thank you for sharing

1 Like