I have a script that’s supposed to make a pet that follows the player around wherever they go. I’ve been doing this, and I do in fact have a working script. I was going to ask, however, into what folder I should put it in so that it works.
local object = workspace.follow -- insert the object you want to follow the player here
local player = game.Players.LocalPlayer
local speed = 20 -- set the speed at which the object will follow the player
while true do
local playerPos = player.Character.HumanoidRootPart.Position
local objectPos = object.Position
local direction = (playerPos - objectPos).Unit
local distance = (playerPos - objectPos).Magnitude
if distance > 5 then -- only moves if distance is greater than 0.1
object.CFrame = object.CFrame + direction * speed * math.min(distance, 1/60)
end
if distance > 10 then
object.CFrame = object.CFrame + direction * 30 * math.min(distance, 1/60)
end
wait()
end
Put in a local script but also have it run for other players to replicate the movement so it’s smooth for all if you are looking for it to be super smooth. Else, if that’s too hard, put it in the server, it’s simple and all can see it, though on the player the object is following, it will lag behind a bit because of ping. Also, CFrames on the server look buggy but not on client. So the best way would be to have a replication system to control the pet smoothly for all players and have the server ignore it, which would also be healthy for the server.
I had to play around with the timing and update to get a smooth follow.
Also not a fan of heartbeat…
LocalScript in StarterPlayerScripts
local object = workspace:WaitForChild("follow")
local player = game.Players.LocalPlayer
object.Anchored = true
local speed = 60
local runService = game:GetService("RunService")
runService.Stepped:Connect(function(_, deltaTime)
local character = player.Character
if character and character:FindFirstChild("HumanoidRootPart") then
local playerPos = character.HumanoidRootPart.Position
local objectPos = object.Position
local direction = (playerPos - objectPos).Unit
local distance = (playerPos - objectPos).Magnitude
if distance > 4 then
local targetPosition = objectPos + direction * speed * deltaTime
object.CFrame = CFrame.new(objectPos):Lerp(CFrame.new(targetPosition), 0.2)
end
end
end)
can you explain some of your code for me? I’m a little new. All I really need explained is just like why you used .Stepped, but I would appreciate a full explanation.
I also noticed a little bit of a bug, where if you stand on the part, it will follow you and allow you to “fly”. I’ll probably solve this by using the part.Touched:Connect.
Well that got complicated real quick… You could just set the pet to CanCollide=false
local object = workspace:WaitForChild("follow")
local player = game.Players.LocalPlayer
local isTouching = false
object.Anchored = true
local speed = 60
local runService = game:GetService("RunService")
object.Touched:Connect(function(hit)
if hit.Parent == player.Character then
local humanoidRoot = player.Character:FindFirstChild("HumanoidRootPart")
if humanoidRoot and hit:IsA("Part") then
local pos = humanoidRoot.Position
local objectPos = object.Position
local distance = (pos - objectPos).Magnitude
if distance < 5 then
local direction = (pos - objectPos).Unit
object.Position = object.Position - direction * 5
end
end
end
end)
runService.Stepped:Connect(function(_, deltaTime)
local character = player.Character
if character and character:FindFirstChild("HumanoidRootPart") then
local playerPos = character.HumanoidRootPart.Position
local objectPos = object.Position
local direction = (playerPos - objectPos).Unit
local distance = (playerPos - objectPos).Magnitude
if distance > 4 then
local targetPosition = objectPos + direction * speed * deltaTime
object.CFrame = CFrame.new(objectPos):Lerp(CFrame.new(targetPosition), 0.2)
end
end
end)
Well I also worked on this a bit, and understandably, we have very different approaches.
Here’s my code at the moment, what do you think?
local object = workspace:WaitForChild("follow")
local player = game.Players.LocalPlayer
object.Anchored = true
local speed = 60
game:GetService("RunService").Stepped:Connect(function(_, deltaTime)
local character = player.Character
if character and character:FindFirstChild("HumanoidRootPart") then
local playerPos = character.HumanoidRootPart.Position
local objectPos = object.Position
local direction = (playerPos - objectPos).Unit
local distance = (playerPos - objectPos).Magnitude
if distance > 4 then
local targetPosition = objectPos + direction * speed * deltaTime
object.CFrame = CFrame.new(objectPos):Lerp(CFrame.new(targetPosition), 0.2)
end
end
object.Touched:Connect(function(hit)
if hit and hit.Parent == player then
object.CFrame = CFrame.new(objectPos)
end
end)
end)```
I'll probably end up using your code, and then the Roblox AI to explain what all of it does, combined with the documentation. Hopefully by the end of this I will become fluent in creating part-that-follow-player systems.
Thanks for your help.
RunService.Stepped is like a top of the frame pause. Normally good for pre-physics updates.
RunService.Heartbeat is like a end of the frame pause. Normally good for object updates after physics simulation.
Despite this I find Stepped to be a more consistent. Could just be me.