Pets System: Parts welded to the PrimaryPart not functioning properly

I am working on a pets system, and the parts welded to the PrimaryPart of a pet stick together, but are not sticking to the PrimaryPart. The other parts also show up closer to the player at the origin of the pet.

Video:

Ignore the test pets, they only have one part in the model

I have tried using regular welds as well, to the same issue.
The PrimaryPart is anchored. Unanchoring them will cause the pets to fall into the void and get deleted

This is the script that handles the pets on the ServerSide (I hardly think this script is the issue, but maybe I am wrong):

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Function to attach pets to a player
local function attachPetsToPlayer(player)
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
	
	local petsFolder = Instance.new("Folder", workspace[player.Name])
	petsFolder.Name = "Pets"

	-- Get equipped pets from player's Pets.EquippedPets
	local equippedPetsString = player:WaitForChild("Pets"):WaitForChild("Equipped").Value
	local petNames = {}
	if equippedPetsString ~= "" then
		petNames = string.split(equippedPetsString, ",")
	end

	-- Clone and setup pets based on equipped pet names
	local pets = {}
	for i, petName in ipairs(petNames) do
		if petName == "Test" then continue end
		
		local petTemplate = ServerStorage.Pets:FindFirstChild(petName)
		if petTemplate then
			local pet = petTemplate:Clone()
			pet.Parent = petsFolder
			pet.Name = player.Name .. "_Pet_" .. i - 1

			local alignPosition = Instance.new("AlignPosition", pet.PrimaryPart)

			local petAttachment = Instance.new("Attachment", pet.PrimaryPart)
			local playerAttachment = humanoidRootPart:FindFirstChild("PetAttachment")
			if not playerAttachment then
				playerAttachment = Instance.new("Attachment", humanoidRootPart)
				playerAttachment.Name = "PetAttachment"
			end

			alignPosition.Attachment0 = petAttachment
			alignPosition.Attachment1 = playerAttachment
			alignPosition.MaxForce = 100000
			alignPosition.Responsiveness = 50

			table.insert(pets, pet)
		end
	end

	-- Update pet positions
	local runServiceConnection
	runServiceConnection = game:GetService("RunService").Heartbeat:Connect(function()
		for i, pet in ipairs(pets) do
			local circlePosition = humanoidRootPart.Position + Vector3.new(
				math.cos(i * (math.pi * 2 / #petNames)) * 8,
				0,
				math.sin(i * (math.pi * 2 / #petNames)) * 8
			)

			-- Move the pet to the circle position
			pet.PrimaryPart.Position = circlePosition
		end
	end)
	
	return runServiceConnection
end

Players.PlayerAdded:Connect(function(player)
	local currentConnection

	player.CharacterAdded:Connect(function()
		currentConnection = attachPetsToPlayer(player)

		player:WaitForChild("Pets"):WaitForChild("Equipped").Changed:Connect(function()
			if currentConnection then
				currentConnection:Disconnect()
			end

			for _, pet in ipairs(petsFolder:GetChildren()) do
				if pet.Name:sub(1, #player.Name) == player.Name then
					pet:Destroy()
				end
			end

			currentConnection = attachPetsToPlayer(player)
		end)
	end)
end)

ReplicatedStorage.EquipUnequipPet.OnServerEvent:Connect(function(player, equippedPetsString, petsString)
	player.Pets.Owned.Value = petsString
	player.Pets.Equipped.Value = equippedPetsString
end)

This is the ClientSide:

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local petsFolder = character:WaitForChild("Pets")

local equippedPets = player:WaitForChild("Pets"):WaitForChild("Equipped")
local numberOfPetsEquipped = string.split(equippedPets.Value, ",")
local petCount = #numberOfPetsEquipped

local circleRadius = 8
local circleSpeed = 0.2
local verticalSpeed = 1
local verticalAmplitude = 0.5

local tweenInfo = TweenInfo.new(
	0.1,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.Out,
	0,
	false, 
	0 
)

local function isPlayerMoving()
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if humanoid then
		return humanoid.MoveDirection.Magnitude > 0
	end
	return false
end

local function updatePets()
	local equippedPets = player:WaitForChild("Pets"):WaitForChild("Equipped")
	local numberOfPetsEquipped = string.split(equippedPets.Value, ",")
	local petCount = #numberOfPetsEquipped - 1

	for i = 1, petCount do
		local pet = petsFolder:FindFirstChild(player.Name .. "_Pet_" .. i)
		if pet then
			local angle = tick() * circleSpeed + (math.pi * 2 / petCount) * (i - 1)
			local circlePosition = humanoidRootPart.Position + Vector3.new(
				math.cos(angle) * circleRadius,
				0,
				math.sin(angle) * circleRadius
			)

			local verticalOffset = math.sin(tick() * verticalSpeed + i * 0.5) * verticalAmplitude
			local targetPosition = circlePosition + Vector3.new(0, verticalOffset, 0)

			local goal = {
				Position = targetPosition
			}
			local tween = TweenService:Create(pet.PrimaryPart, tweenInfo, goal)
			tween:Play()

			if isPlayerMoving() then
				local forwardCFrame = CFrame.new(targetPosition, targetPosition + humanoidRootPart.CFrame.LookVector)
				pet:SetPrimaryPartCFrame(forwardCFrame)
			else
				local facePlayerCFrame = CFrame.new(targetPosition, humanoidRootPart.Position)
				pet:SetPrimaryPartCFrame(facePlayerCFrame)
			end
		end
	end
end

RunService.Heartbeat:Connect(function()
	updatePets()
end)

You should use WeldConstraint to weld the parts in the studio.

I am using WeldConstraint, the same issue occurs

I figured it out, it turns out it was the server script.

pet.PrimaryPart.Position = circlePosition

I set the position instead of using SetPrimaryPartCFrame

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