I am trying to use a Tween to smoothly move a Part. My current script creates a part, then moves it to a target over the course of a second. For some reason the part's position cannot be changed via script or the move tool after being moved.
Here's my LocalScript, which binds the creation and movement of a Part to a TextButton.
local tweenService = game:GetService("TweenService")
local runService = game:GetService("RunService")
local player = game.Players.LocalPlayer
local RunServiceEvent = nil
local tweenInfo = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)
function SpawnPart()
local part = Instance.new("Part")
part.Anchored = true
part.Parent = game.Workspace.Clutter.Coins
local startPos = Vector3.new(0, 2, 0)
part.Position = startPos
local TargetPosition = Vector3.new(5, 2, 0)
local Tween = tweenService:Create(part, tweenInfo, {Position = TargetPosition})
Tween:Play()
local StartTime = tick()
RunServiceEvent = runService.RenderStepped:Connect(function()
local Time = (tick() - StartTime) / tweenInfo.Time
if part == nil then return end
if Time > 1 then
part.Position = TargetPosition
return
end
end)
task.spawn(function()
Tween.Completed:Wait()
task.wait()
RunServiceEvent = nil
end)
end
player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("TextButton").Activated:Connect(SpawnPart)
To reproduce, create the following structure, then play the game and click the GUI button.
├── StarterGui
│ ├── ScreenGui
│ │ ├── TextButton
├── StarterPlayer
│ ├── StarterPlayerScripts
│ │ ├── LocalScript
After the Tween finishes, the move tool (or trying to move via script) no longer has any affect on the new part.
You can also download this .rbxl file: TestPlace
The problem is in the work you're doing with RunServiceEvent
. It seems like you're trying to make sure the part is at its target position once the Tween is over, then deleting the RenderStepped
. Unfortunately, RunServiceEvent = nil
won't delete it for you - it unbinds the object from that name, but it doesn't delete the object from memory.
This means that after one second, your script will constantly move the part to your target position, effectively locking it in place.
The good news is, you don't need that bit at all! Your Script works fine if you just remove that bit entirely:
local tweenService = game:GetService("TweenService")
local runService = game:GetService("RunService")
local player = game.Players.LocalPlayer
local RunServiceEvent = nil
local tweenInfo = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)
function SpawnPart()
local part = Instance.new("Part")
part.Anchored = true
part.Parent = game.Workspace.Clutter.Coins
local startPos = Vector3.new(0, 2, 0)
part.Position = startPos
local TargetPosition = Vector3.new(5, 2, 0)
local Tween = tweenService:Create(part, tweenInfo, {Position = TargetPosition})
Tween:Play()
end
player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("TextButton").Activated:Connect(SpawnPart)
If you really want to ensure that the part ends up in the right place, you can also just make your script wait until the Tween is done using task.delay
:
local tweenService = game:GetService("TweenService")
local runService = game:GetService("RunService")
local player = game.Players.LocalPlayer
local RunServiceEvent = nil
local tweenInfo = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)
function SpawnPart()
local part = Instance.new("Part")
part.Anchored = true
part.Parent = game.Workspace.Clutter.Coins
local startPos = Vector3.new(0, 2, 0)
part.Position = startPos
local TargetPosition = Vector3.new(5, 2, 0)
local Tween = tweenService:Create(part, tweenInfo, {Position = TargetPosition})
Tween:Play()
task.delay(tweenInfo.Time, function()
part.Position = TargetPosition
end)
end
player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("TextButton").Activated:Connect(SpawnPart)