I just made this pet follow system that will make pets follow the player in a circle
I made it work but its client sided and I want to change that.
I tried doing the same things from the local script but with Stepped instead of Heartbeat and it made my frames lower + it was not smooth
I also tried using a remote event every time heartbeat is fired and it’s that same result
local Character = script.Parent
local hrp = Character:FindFirstChild("HumanoidRootPart")
local Pets = {}
local numberOfParts = 8
wait(0.5)
for i, Pet in ipairs(script:GetChildren()) do
table.insert(Pets, Pet)
end
for _, part in pairs(Pets) do
if part:IsA("Model") then
for _,ModelPart in ipairs(part:GetChildren()) do
if ModelPart ~= part.PrimaryPart then
ModelPart.Anchored = false
else
ModelPart.Anchored = true
end
ModelPart.CanCollide = false
end
part.Parent = workspace
else
part.Anchored = true
part.CanCollide = false
part.Parent = workspace
end
end
local function getXAndZPositions(angle)
local x = math.cos(angle) * 5
local z = math.sin(angle) * 5
return x, z
end
game:GetService("RunService").Heartbeat:Connect(function()
for i, part in pairs(Pets) do
local angle = i * ((math.pi * 2) / #Pets)
local x, z = getXAndZPositions(angle)
local position = (hrp.CFrame * CFrame.new(x, 0, z)).p
local lookAt = hrp.Position
local tween = nil
if part:IsA("Model") then
tween = game:GetService("TweenService"):Create(part.PrimaryPart,TweenInfo.new(0.5),{CFrame = CFrame.new(position, lookAt)})
else
tween = game:GetService("TweenService"):Create(part,TweenInfo.new(0.5),{CFrame = CFrame.new(position, lookAt)})
end
tween:Play()
end
end)
also, I didn’t make the full system, this is just for testing and that’s why the pets are the children of the script
I want everyone to see the tween, also what I meant was that I did Stepped in a server script and this is how it looks https://gyazo.com/a91c2f35088d5facb38c7f82f24d9be8
as you see its not smooth at all and it causes frame rate issues
You can handle it in the client, use RemoteEvents to make it work
Just send the necessary things to the client(s) like CFrame.new(position, lookAt) and the pet model
Just set the CFrame in the server
A simple solution would simply be to have every client handle it separately.
I would say for the most part, the server should never have to handle anything visual. The client should deal with that. If you’re worried about syncing, just use remotes to communicate things to each client. If it’s just a matter of pets moving around a player, I doubt their exact position matters. Just that they’re there.
I just tried doing that with FireAllClients in the remote, it looks smoother but not 100% smooth and after something like 10 seconds you will get less frame rates and after 30 seconds or even less the game will not be playable
Sounds like you’re doing something inefficiently somewhere. Perhaps even replicating things. If handled properly, there shouldn’t be any issues like that.
local Character = script.Parent
local hrp = Character:FindFirstChild("HumanoidRootPart")
local Pets = {}
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(Character)
wait()
local hrp = Character:FindFirstChild("HumanoidRootPart")
game:GetService("RunService").Stepped:Connect(function()
if not Character then return end
game.ReplicatedStorage.MovePets:FireAllClients(Pets, hrp)
end)
end)
end)
wait(1)
for i, Pet in ipairs(script:GetChildren()) do
table.insert(Pets, Pet:Clone())
end
for _, part in pairs(Pets) do
if part:IsA("Model") then
for _,ModelPart in ipairs(part:GetChildren()) do
if part.PrimaryPart ~= ModelPart then
ModelPart.Anchored = false
else
ModelPart.Anchored = true
end
ModelPart.CanCollide = false
end
part.Parent = workspace
else
part.Anchored = true
part.CanCollide = false
part.Parent = workspace
end
end
server
local function getXAndZPositions(angle)
local x = math.cos(angle) * 5
local z = math.sin(angle) * 5
return x, z
end
game.ReplicatedStorage.MovePets.OnClientEvent:Connect(function(Pets, hrp)
for i, part in pairs(Pets) do
local angle = i * ((math.pi * 2) / #Pets)
local x, z = getXAndZPositions(angle)
local position = (hrp.CFrame * CFrame.new(x, 0, z)).p
local lookAt = hrp.Position
local tween = nil
if part:IsA("Model") then
tween = game:GetService("TweenService"):Create(part.PrimaryPart,TweenInfo.new(0.5),{CFrame = CFrame.new(position, lookAt)})
else
tween = game:GetService("TweenService"):Create(part,TweenInfo.new(0.5),{CFrame = CFrame.new(position, lookAt)})
end
tween:Play()
end
print("Beat")
end)
Yeah so you’re having the server FireAllClients every step. What I meant was to simply tell all clients when a pet is equipped or unequipped. Then have each client handle movement completely. But there’s more than one way of doing that, depending on how you want to set things up.
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(Character)
wait()
local hrp = Character:FindFirstChild("HumanoidRootPart")
game:GetService("RunService").Stepped:Connect(function()
if not Character then return end
game.ReplicatedStorage.MovePets:FireAllClients(Pets, hrp)
end)
end)
end)
The reason why it’s unplayable is because of game.Players.PlayerAdded, each time a player joins, it creates a new thread of RunService.Stepped, why not put
game:GetService("RunService").Stepped:Connect(function()
if not Character then return end
game.ReplicatedStorage.MovePets:FireAllClients(Pets, hrp)
end)
Outside the PlayerAdded event, and store all the joining player’s character in a table?
Then on replicating the movements to the client:
local NEXT_PING_INTERVAL = 1
local n = 0
local sendToClients = Instance.new("BindableEvent")
game:GetService("RunService").Heartbeat:Connect(function(dt)
n = math.min(n + dt, NEXT_PING_INTERVAL)
if n >= NEXT_PING_INTERVAL then -- sending alot of remotes to the client will stress the network I think, professionals, please correct me if im wrong
local hrps = {}
for playerName, character in pairs(STORED_CHARACTER_TABLE) do
if not character then return end
table.insert(hrps, character.HumanoidRootPart)
end
sendToClients:Fire(hrps)
end
end)
sendToClients.Event:Connect(function(hrps)
MovePets:FireAllClients(Pets, hrps)
end)
--!! This code is not tested
Let the server make the part network owner as client, and any local changes to the part position by a local script will affect the server, so you don’t need any complex system, however you can make it complex but easier would be easy