Can someone tell me why this is not working?

Im making a pet system and it wont work!

Heres my code.


	function Pets:FollowChar(Pet,PetOwner,Pos)
	
		if not PetOwner then return end
		local HumanoidRootPart = PetOwner:FindFirstChild("HumanoidRootPart")
	
		local Bp = Pet:FindFirstChildOfClass("BodyPosition") or Instance.new("BodyPosition")
		Bp.P = 3000
		Bp.D = 250
		Bp.Position = Pos
		if not Pet:FindFirstChildOfClass("BodyPosition") then
			Bp.Parent = Pet
		end
		print(Pet)
		
	end
	
	
	function Pets:GetPetPosition(Pet,PetOwner)

		
		local HumanoidRootPart : BasePart = PetOwner:FindFirstChild("HumanoidRootPart")
	
		
		local PetPositionCFrame = HumanoidRootPart.CFrame.LookVector - Vector3.new(0,0,5)
		return PetPositionCFrame
	end
1 Like

I believe the issue is that the force is too small, the part is not massless and is also collidable which could make it have friction.

However, I really don’t recommend using physics at all for a pet system. Not only it can be exploited to fling players around, it is going to lag the server with many pets.

Could you provide the server script too so we can do a better system, such as moving the pet’s around the player?

1 Like

I have no idea what else to use then.

yes, but the server is completely unfinished and i only have it for testing. so dont mind the bad code.

wait(3)
local petMod = require(game.ServerScriptService.Pets)



local pet = petMod:new(script.Parent,game.Players:FindFirstChildOfClass("Player").Character) -- i doing this because i wanted to test without making a whole script lol


game["Run Service"].Heartbeat:Connect(function()
	local pos = petMod:GetPetPosition(pet.Pet,pet.PetOwner)
	petMod:FollowChar(pet.Pet,pet.PetOwner,pos)
end)


1 Like

My approach was using a system that automatically set’s the position of pet’s around the player. It’s not the best solution because it is server dependant but it can be developed further so player’s are the ones that render pets for themselves and other player’s reducing the strain on the server and removing the local delay.

Here’s the code (added a bunch of comments with AI so you understand what each part does)

I’ve also reformatted it so it’s more readable and usable.

Server script

local Pet = require(game.ServerScriptService.Pets) -- Require the Pets module.

-- Services
local Players = game:GetService("Players")

-- when a player joins, give him a test pet.
Players.PlayerAdded:Connect(function (player)
	local playerPet = Pet.new(player) -- Give the player a pet when they join.

	-- small test loop that gives a pet to the player every few seconds
	task.spawn(function() -- Use task.spawn to run this in a new thread so it doesn't yield the PlayerAdded connection.
		local lastWait = 5
		while true do
			local newPet = Pet.new(player) -- Give the player another pet.

			print(Pet) -- Print the Pet module (for debugging).
			task.wait(lastWait) -- Wait before giving another pet.
			lastWait += 5 -- Increase the wait time.
		end
	end)
end)

– Module script

-- module
local Pets = {}
Pets.__index = Pets

-- variables

-- players and their owned pets with a type so we understand the structure.
-- This type definition helps with understanding the structure of serverPets.
type PlayerPetArray = { [Player]: {typeof(setmetatable({}, Pets))} }
-- serverPets stores a table of pets for each player.  The keys are Player objects, and the values are arrays of pet objects.
local serverPets: PlayerPetArray = {}

-- This function creates a new entry in serverPets for a player if one doesn't exist.
local function createEntry(player: Player)
	serverPets[player] = {} -- Initialize an empty table for the player's pets.
	return {} -- Return an empty table.  This isn't strictly necessary, but it mirrors how Pets.new works.
end

local methods = {} -- This table will hold the methods for the Pet objects.
function Pets.new(player: Player)
	-- get the player's owned pets or create a new empty table of pets
	-- If the player already has pets, retrieve them; otherwise, create a new entry for the player.
	local theirPets = serverPets[player] or createEntry(player)

	-- Create a new part to represent the pet.
	local newPet = Instance.new("Part")
	newPet.Anchored = true
	newPet.CanCollide = false
	newPet.Size = Vector3.new(2, 2, 2)
	newPet.Name = `{player.Name}'s Pet ({#theirPets})` -- Give the pet a name based on the player and pet count.
	newPet.Parent = workspace -- Parent the pet to the workspace.

	table.insert(serverPets[player], newPet) -- Add the new pet's part to the player's pet array.

	-- pet properties (example)
	-- Create a new pet object using a metatable to give it methods.
	local self = setmetatable({}, Pets)
	self.petName = "john" -- Example pet name.
	self.petRarity = "ultra rare glowy" -- Example pet rarity.
	self.instance = newPet -- Store the pet's part instance.

	return self -- Return the new pet object.
end

-- Method to move the pet.
function Pets:Move(newCFrame: CFrame)
	local instance: Part = self.instance -- Get the pet's part instance.
	instance.CFrame = newCFrame -- Set the pet's CFrame.
end

local RunService = game:GetService("RunService")

-- This function is called every heartbeat to update the pet positions.
local function onHeartbeat(deltaTime: number)
	for player, petArray in pairs(serverPets) do -- Iterate through each player and their pets.
		local character = player.Character -- Get the player's character.
		if character then
			local hrp = character:FindFirstChild("HumanoidRootPart") -- Get the HumanoidRootPart.
			if hrp then
				local baseCFrame = hrp.CFrame -- Get the HRP's CFrame.
				local position = baseCFrame.Position -- Get the HRP's position.
				local rightVec = baseCFrame.RightVector -- Get the HRP's right vector.
				local petCount = #petArray -- Get the number of pets the player has.
				for i, pet in ipairs(petArray) do -- Iterate through each of the player's pets.
					local targetPos: Vector3 -- Declare the target position.
					local offsetDistance = 5 -- Distance between the player and the pets.
					if petCount == 2 then -- Special case for two pets: one on each side.
						if i == 1 then
							targetPos = position + rightVec * offsetDistance
						else -- i == 2
							targetPos = position - rightVec * offsetDistance
						end
					else -- For more than two pets, arrange them in a circle.
						local angle = (2 * math.pi / petCount) * (i - 1) -- Calculate the angle for each pet.
						local offset = Vector3.new(math.cos(angle) * offsetDistance, 0, math.sin(angle) * offsetDistance) -- Calculate the offset.
						targetPos = position + baseCFrame:VectorToWorldSpace(offset) -- Apply the offset relative to the player's CFrame.
					end
					local targetCFrame = CFrame.new(targetPos) -- Create the target CFrame.
					local lerpAlpha = math.clamp(10 * deltaTime, 0, 1) -- Calculate the interpolation alpha.
					pet.CFrame = pet.CFrame:Lerp(targetCFrame, lerpAlpha) -- Smoothly move the pet to the target position.
				end
			end
		end
	end
end

RunService.Heartbeat:Connect(onHeartbeat) -- Connect the onHeartbeat function to RunService.Heartbeat.  This makes the pets follow the player.

return Pets -- Return the Pets module.

1 Like

I will try this right now, Thank you!!

Thank you soo muchh!!! it work so good

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.