Hello Devforum! I have been making moving platforms using tween service but I have a problem where the player doesn’t move with the platform. I have researched this issue and found the topic: Moving platform for players using TweenService?. The only problem after reading this topic is that I couldn’t really understand what was happening. I read the topics provided, but was still very confused on what to do. The solution also did not make sense to me. Do I have to create a body gyro and body position in my platform and then tween them? How do I tween them with my code?
My script:
local tweenservice = game:GetService("TweenService")
for i, object in pairs(game.Workspace:GetChildren()) do
if object:IsA("Folder") then
if object:FindFirstChild("IsTower") then
local tower = object
if tower:FindFirstChild("MovingPlatforms") then --got folder with platforms
local movingplatforms = tower.MovingPlatforms:GetChildren() --gets all moving platforms
for i, moveplatform in pairs(movingplatforms) do
coroutine.wrap(function()
while true do
--Tweening code
local tweeninfo = TweenInfo.new(moveplatform.Time.Value)
local goal = {}
goal.CFrame = moveplatform.Finish.CFrame
local tween = tweenservice:Create(moveplatform.SpaceshipMove.PrimaryPart, tweeninfo, goal)
tween:Play()
wait(5)
local tweeninfo = TweenInfo.new(moveplatform.Time.Value)
local goal = {}
goal.CFrame = moveplatform.Start.CFrame
local tween = tweenservice:Create(moveplatform.SpaceshipMove.PrimaryPart, tweeninfo, goal)
tween:Play()
wait(5)
end
end)()
end
end
end
end
end
If I could get an explanation on how to do this in the future, I would really appreciate it!
Hello there. So, from what I can understand, you are moving the primary part itself using CFrame? If so, then that is the issue.
When moving parts via CFrame, they are not counted as “Physics Objects” per say, so they will not move the player along with themselves. An easy way to fix that is to use a BodyPosition attribute (along with a BodyGyro so it does not spin around) and then change the Position of the BodyPosition using TweenService.
Example
Here is how the explorer looks like:
Here is the script that I used:
-- Services --
local TweenService = game:GetService("TweenService")
-- Variables --
local Start = workspace.Start -- Anchored brick at the start location
local End = workspace.End -- Anchored brick at the end location
local BodyPos = script.Parent -- BodyPosition force
local TweenInfo_ = TweenInfo.new(3, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
-- Scripting --
while true do
local Completed = false
local Tween = TweenService:Create(BodyPos, TweenInfo_, {Position = End.Position})
Tween:Play()
Tween.Completed:connect(function()
Completed = true
end)
repeat wait() until Completed
wait(5)
Completed = false
local Tween2 = TweenService:Create(BodyPos, TweenInfo_, {Position = Start.Position})
Tween2:Play()
Tween2.Completed:connect(function()
Completed = true
end)
repeat wait() until Completed
wait(5)
end
Of course, you could optimize this more. I highly suggest you move the platforms locally as it will prevent lag and reduce the amount of people falling off at high speeds due to NetworkReplication.
Alternatively, you could another method which is not physics based but ensures people don’t fall from platform. You can find details about this one here.
I hope this helped you understand your problem better and even solved it. If you have any questions, feel free to ask.
Thank you for your response! I think I understand a bit more. I tried implementing most of ur script into my script and tweaked it to fit my needs, but it isn’t working as planned. There are no errors and it prints the print statement I put at the beginning of the loop and after the tween plays. Here is my current script. I am not sure what I did wrong.
local tweenservice = game:GetService("TweenService")
for i, object in pairs(game.Workspace:GetChildren()) do
if object:IsA("Folder") then
if object:FindFirstChild("IsTower") then
local tower = object
if tower:FindFirstChild("MovingPlatforms") then
local movingplatforms = tower.MovingPlatforms:GetChildren()
for i, moveplatform in pairs(movingplatforms) do
coroutine.wrap(function()
local start = moveplatform:WaitForChild("Start") --start
local finish = moveplatform:WaitForChild("Finish") --finish
local seconds = moveplatform:WaitForChild("Time") --time for waiting value
local bodypos = moveplatform:WaitForChild("SpaceshipMove").Move.BodyPosition --getting the body pos from the move part
local tweeninfo = TweenInfo.new(3, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut) --tweeninfo identical to yours
while true do --start of loop
print("ye") --print statement (prints by the way)
local completed = false
local tween = tweenservice:Create(bodypos, tweeninfo, {position = finish.Position})
tween:Play() --plays tween but doesnt
print("Played") --prints played though
tween.Completed:connect(function()
completed = true
end)
repeat wait() until completed
wait(seconds.Value)
completed = false
local tween2 = tweenservice:Create(bodypos, tweeninfo, {position = start.Position})
tween2:Play()
tween2.Completed:Connect(function()
completed = true
end)
repeat wait() until completed
wait(seconds.Value)
end
end)()
end
end
end
end
end
An error that I did notice was that the “p” in position was NOT capitalized, which will just cause an error. After testing it as well, I did confirm that this causes issues:
If I am correct, you just need to change the position to Position in {position = start.Position} and {position = finish.Position} and it should work as intended.
(Disregard the above as this is an issue when using the part’s position, not the BodyPosition property)
If you could provide more information and more details on what the issue is (so tell me if the issue is that it is not moving, or if the player is not moving along with the platform, etc) and what the output is (such as “ye”, “Played”, anything else that you might put there, or nothing), then I can understand better what is causing the problem and possibly help you fix it.
Oops! I am sorry about that. So yes, the platform is not moving at all, but the print statements at the beginning of the loop are indicating that the tween is being played, which it is not. I looked at all the moving platforms in my game and none of them were moving although the print statements printed 4 times, the number of platforms in my game.
Are you sure that the platform isn’t anchored? If it is, then it’s not going to be moving at all. It is a physics object, therefore it needs to be unanchored (and everything welded / attached to it as well) for it to work.
Creating a platform that moves with the player’s Character can be achieved in different ways; however, it appears that utilizing raycasting allows for much more flexibility under certain circumstances & is good enough for games such as Jailbreak and The Wild West to make use of it.
Background Info
When I tried to create the same kind of moving platform, the topic that you referenced in the OP is one that I read through as well but I faced similar challenges with trying to make sense of it, too.
However, I later came across a topic that tyridge77 and badcc had responded to in order to answer questions about how they achieved such effects in the games they’ve implemented trains into.
During that topic, someone provided an example of how it could be done based on the input of badcc and tyridge77, and I worked off of one of the examples until I came across an issue that was resolved with the help of another user (which is outlined in the following topic):
Resources
I would suggest reading through the topic that badcc & tyridge provided insight into in addition to the topic I created about solving the issue that was encountered in case it’s able to provide enough information that makes sense.
In summary, the platforms can be Tweened on their own and raycasting can be utilized to determine how far the player’s Character has moved since the last frame in order to update their position and keep them on the platform. While I haven’t had too much experience with raycasting prior to this, I can elaborate/explain in more detail, if needed.
(For ease of access/without needing to open the place file, the following codeblock handles the raycasting which would go into a LocalScript in StarterCharacterScripts)
Click here to see the code
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local lastObjectRaycasted
local lastObjectCFrame
local Function
local Function2
local Whitelist = {workspace.MovableItems.MovingParts}
Function = RunService.Heartbeat:Connect(function()
local Character = player.Character or player.CharacterAdded:Wait()
local Humanoid = Character.Humanoid
local HumanoidRootPart = Character.HumanoidRootPart
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = Whitelist
raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
local raycastParams2 = RaycastParams.new()
raycastParams2.FilterDescendantsInstances = {lastObjectRaycasted}
raycastParams2.FilterType = Enum.RaycastFilterType.Whitelist
local downVector = HumanoidRootPart.CFrame.UpVector * -13
local moveDirection = Humanoid.MoveDirection * 2.5
local angle = downVector - Vector3.new(moveDirection.X, 0, moveDirection.Z)
local RaycastResult = workspace:Raycast(HumanoidRootPart.CFrame.Position, angle, raycastParams)
local lastObjectRaycastedRaycastResult = workspace:Raycast(HumanoidRootPart.CFrame.Position, angle, raycastParams2)
local updatedInfo
if lastObjectRaycasted and lastObjectRaycastedRaycastResult then
updatedInfo = lastObjectRaycastedRaycastResult
else
updatedInfo = RaycastResult
lastObjectRaycasted = nil
end
if updatedInfo then
local distance = (HumanoidRootPart.CFrame.Position - updatedInfo.Position).Magnitude
local visualizer = Instance.new("Part")
visualizer.Anchored = true
visualizer.Transparency = 0.5
visualizer.BrickColor = BrickColor.new("New Yeller")
visualizer.CanCollide = false
visualizer.Size = Vector3.new(0.1, 0.1, distance)
visualizer.CFrame = CFrame.lookAt(HumanoidRootPart.CFrame.Position, updatedInfo.Position) * CFrame.new(0, 0, -distance/2)
visualizer.Parent = workspace
local raycastInstance = updatedInfo.Instance
if not lastObjectCFrame then
lastObjectCFrame = raycastInstance.CFrame
end
local currentCFrame
if lastObjectRaycasted and raycastInstance ~= lastObjectRaycasted then
currentCFrame = lastObjectRaycasted.CFrame
else
currentCFrame = raycastInstance.CFrame
end
local relativeDistance = currentCFrame * lastObjectCFrame:Inverse()
HumanoidRootPart.CFrame = relativeDistance * HumanoidRootPart.CFrame
lastObjectRaycasted = raycastInstance
lastObjectCFrame = raycastInstance.CFrame
else
lastObjectCFrame = nil
end
if not Function2 then
Function2 = player.Character.Humanoid.Died:Connect(function()
Function:Disconnect()
Function2:Disconnect()
end)
end
end)
More info about Raycasting can be found on the following pages: