How to make a player stick to a moving part

Hi,

I’m really struggling with this, appreciate any help.

I have a platform which has 4 directional arrow buttons to move the platform when the player stands on it.
I can move the platform and its children fine but the player stays in place. I want the player to move with the platform. I’ve had various success achieving this where I was able to move the player with the platform but then I couldn’t freely move the player with the usual wasd controls. I still want the player to be able to run/jump while on the platform - just when they are still they should move with the platform as opposed to remaining in the same spot whilst the platform moves without them.

I’ve attached my code as well in the hope it helps.

-- Services

local RunService = game:GetService("RunService")

-- Vars

-- Grouping for this obby stage
local stage = workspace.Stage

-- The grouping containing the moving platform and buttons to move it
local platform = stage.Platform

-- Moving platform

local keyCodeToDirectionMap = {
	[Enum.KeyCode.W] = Vector3.new(0, 0, -1),
	[Enum.KeyCode.A] = Vector3.new(-1, 0, 0),
	[Enum.KeyCode.S] = Vector3.new(0, 0, 1),
	[Enum.KeyCode.D] = Vector3.new(1, 0, 0),
}
local keyCodeToIsPressedMap = {
	[Enum.KeyCode.W] = false,
	[Enum.KeyCode.A] = false,
	[Enum.KeyCode.S] = false,
	[Enum.KeyCode.D] = false,
}

-- Get the direction(s) to platform should move
local function getDirectionsToProcess()
	local directions = {}
	for keyCode, isPressed in pairs(keyCodeToIsPressedMap) do
		if isPressed then
			local direction = keyCodeToDirectionMap[keyCode]
			table.insert(directions, direction)
		end
	end
	return directions
end

-- Handle moving the platform and all its children parts
local function managePartMovement(step)
	local directions = getDirectionsToProcess()
	if #directions == 0 then return end
	local targetVelocity = 10 -- Measured in studs per second.
	local function moveParts(object)
		for _, child in ipairs(object:GetChildren()) do
			if child:IsA("BasePart") then
				local targetPosition = child.CFrame
				for _, direction in ipairs(directions) do
					local offset = (targetVelocity * step) * direction
					targetPosition = targetPosition + offset
				end
				child.CFrame = targetPosition
			end
			moveParts(child)
		end
	end
	moveParts(platform)
end
RunService.Heartbeat:Connect(managePartMovement)


-- [Move platform] Button pressing

local buttons = {
	platform.backButton, 
	platform.forwardButton, 
	platform.leftButton, 
	platform.rightButton
}

for _, button in pairs(buttons) do
	local keyCodeStr = button:GetAttribute("KeyCode")
	local keyCode = Enum.KeyCode[string.upper(keyCodeStr)]

	local function deselectButton()
		keyCodeToIsPressedMap[keyCode] = false
	end

	local function selectButton()
		keyCodeToIsPressedMap[keyCode] = true
	end

	button.Touched:Connect(function (otherPart)
		--[[
		Here I handle pressing the four arrow buttons. Calling selectButton() when the player
		steps on the button. And calling deselectButton() when they step off the button.
		]]--
	end)
end

I’ve attempted to read/find other answers using Prismatic Constraint or BodyPosition etc and I could never work it out - get it to work properly. Clearly I’m doing something wrong.

I want my platform to move in the direction of the arrow button(s) being pressed when they are being stood on AND I want the player to move with that same platform.

Thanks so much for reading and any help/code you can provide.

2 Likes

Use one of the many constraint instances to attach the player to the platform.

There are a few ways to do this:

  • As Limited_Unique said, you can use constraints.
    • This can be limited, especially if you want jumping. Jailbreak did something like this a while ago for their train before the third option below was updated to work well.
  • You can also write some code that detects when a player enters and leaves a platform.
    • While a player is on the platform, it moves their CFrame the same way the platform CFrame is being changed. This works well with jumping and other player movement.
  • Probably the easiest way, instead of setting the position or CFrame of the platform, use a body mover (probably a BodyPosition) to move the platform.
    • Characters “stick” to platforms that are being moved with physics.
6 Likes

Thanks for the reply.

I did try the first option but I couldn’t get it to work well, and as you mentioned, I still wanted the player to move/jump.

The second option was the closest I got to a solution. In that it did move the player with the platform, but once the platform was moving, I was unable to move my player or jump away from my button.

I guess BodyPosition sounds ideal. I did have a play but again was unable to get it to work correctly. The examples I found required the platform to be unanchored - but then my platform just disappears.

Do you have any code/steps I could try for the 3rd option? Again I really appreciate the help, I’ve been stuck on this more than I care to admit :disappointed_relieved:

Thank you

1 Like

Okay thanks I managed to get it working using the BodyPosition and BodyGyro.
I did have to make my platform unanchored - which I did in code after I set the Position property of BodyPosition to the platforms initial position.

local platform = platform.MovingPlatform
local platformBodyPosition = platform.BodyPosition
local platformBodyGyro = platform.BodyGyro

platformBodyPosition.Position = platform.Position
platformBodyPosition.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
platformBodyPosition.D = 500
platformBodyPosition.P = 10000

platformBodyGyro.D = 500
platformBodyGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
platformBodyGyro.P = 3000
platformBodyGyro.CFrame = platform.CFrame

platform.Anchored = false

And then my movement code became:

local targetVelocity = 5 -- Measured in studs per second.
local targetPosition = platformBodyPosition.Position
for _, direction in ipairs(directions) do
	local offset = (targetVelocity * step) * direction
	targetPosition = targetPosition + offset
end
platformBodyPosition.Position = targetPosition

Thanks so much

1 Like

Whilst BodyPosition did fix my initial issue, after a while I noticed it stops gripping the player, resulting in the player falling off the button/platform. I’ve opened a separate post to discuss this if anybody can help: BodyPosition after a while no longer grips player to moving platform

Thanks so much

In the end I removed the BodyPosition code due to this bug. The solution I went with in the end can be found here:

2 Likes