Creating a Simulator Pet System

Hey, I’m trying to create a rather simple Simulator Pet System where you click on a pet in your inventory and then the pet is replicated to a physical model; could someone review my code and help me figure out why I’m experiencing this bug where the the pets overlap.

local function CharacterAdded(Character)
	local PlayerInstance
	
	for _, Player in pairs(game:GetService("Players"):GetPlayers()) do
		if Player.Name == Character.Name then PlayerInstance = Player end
	end
	for i,v in pairs(PlayerInstance:WaitForChild("EquippedPets"):GetChildren()) do
		if v.PetId.Value ~= nil then
			if not game:GetService("ReplicatedStorage"):WaitForChild("Pets"):FindFirstChild(v.PetId.Value) then return end
			local Pet = game:GetService("ReplicatedStorage"):WaitForChild("Pets"):FindFirstChild(v.PetId.Value):Clone()
			
			local IdentificationNumber = Instance.new("NumberValue")
			IdentificationNumber.Name = "PetNumber"
			IdentificationNumber.Value = v.PetNumber.Value
			IdentificationNumber.Parent = Pet
			
			Pet.Parent = PlayerInstance.Character:FindFirstChild("Equipped Pets Folder")
			wait(0.1)
			Pet.PrimaryPart:SetNetworkOwner(PlayerInstance)
		end
	end
end

game.Players.PlayerAdded:Connect(function(Player)
	
	local PlayerData = require(script.Parent.DATASTORE.DATASTORE).getData(Player)
	delay(2, function()
		Player.CharacterAdded:Connect(CharacterAdded)
	
		for i,v in pairs(Player.EquippedPets:GetChildren()) do
			if v.PetId.Value ~= nil then
				if not game:GetService("ReplicatedStorage"):WaitForChild("Pets"):FindFirstChild(v.PetId.Value) then return end
				local Pet = game:GetService("ReplicatedStorage"):WaitForChild("Pets"):FindFirstChild(v.PetId.Value):Clone()
				
				local IdentificationNumber = Instance.new("NumberValue")
				IdentificationNumber.Name = "PetNumber"
				IdentificationNumber.Value = v.PetNumber.Value
				IdentificationNumber.Parent = Pet
				
				Pet.Parent = Player.Character:FindFirstChild("Equipped Pets Folder")
				wait(0.1)
				Pet.PrimaryPart:SetNetworkOwner(Player)
			end
		end
	end)
	
	
end)

game:GetService("ReplicatedStorage"):WaitForChild("Remotes").Equip.OnServerEvent:Connect(function(Player, PetName)
	local Pet = game:GetService("ReplicatedStorage"):WaitForChild("Pets"):FindFirstChild(PetName)
	
	local PetInInventory = false
	
	for i,v in pairs(Player.Inventory.Pets:GetChildren()) do
		if Player.Inventory.Pets[i].Value == PetName then
			PetInInventory = true
			break
		end
	end
	
	if Pet and PetInInventory == true and Player.Stats.CurrentEquippedPets.Value < Player.Stats.MaxEquippedPets.Value and Player.Stats.CurrentEquippedPets.Value >= 0 then
		for i,v in pairs(Player.EquippedPets:GetChildren()) do
			if Player.EquippedPets['Pet'..i].PetId.Value == "" then
				Player.EquippedPets['Pet'..i].PetId.Value = PetName
				local Pet = game:GetService("ReplicatedStorage"):WaitForChild("Pets"):FindFirstChild(PetName):Clone()
				
				local IdentificationNumber = Instance.new("NumberValue")
				IdentificationNumber.Name = "PetNumber"
				IdentificationNumber.Value = Player.EquippedPets['Pet'..i].PetNumber.Value
				IdentificationNumber.Parent = Pet
				
				Player.Stats.CurrentEquippedPets.Value = Player.Stats.CurrentEquippedPets.Value + 1
				
				Pet.Parent = Player.Character:FindFirstChild("Equipped Pets Folder")
				wait(0.1)
				Pet.PrimaryPart:SetNetworkOwner(Player)
				break
			end
		end
	end
end)

game:GetService("ReplicatedStorage"):WaitForChild("Remotes").Unequip.OnServerEvent:Connect(function(Player, PetName)
	local Pet = Player.Character['Equipped Pets Folder'][PetName]
		
	if Pet and Player.Stats.CurrentEquippedPets.Value > 0 then
		for i,v in pairs(Player.EquippedPets:GetChildren()) do
			if Player.EquippedPets['Pet'..i].PetId.Value ~= "" then
				Player.EquippedPets['Pet'..i].PetId.Value = ""
				Pet:Destroy()
				
				Player.Stats.CurrentEquippedPets.Value = Player.Stats.CurrentEquippedPets.Value - 1
				break
			end
		end
	end
end)

Server script ^

local BodyPosition = script.Parent.Hitbox:WaitForChild("BodyPosition")
local BodyGyro = script.Parent.Hitbox:WaitForChild("BodyGyro")

while true do
	wait();
	if game:GetService("Players").LocalPlayer.Character then
		break;
	end;
end

local Player = game.Players.LocalPlayer
local Character = Player.Character
local PetVariable = script.Parent
local RequirementsPetsFolder = Character:WaitForChild("Equipped Pets Folder")
local ManipulationVariable = nil

for Var1, Var2 in pairs(RequirementsPetsFolder:GetChildren()) do
	if Var2:WaitForChild("PetNumber").Value ~= nil then
		print(Var2.PetNumber.Value, game:GetService("ReplicatedStorage").PlayerParts.EquippedPets['Pet'..Var2.PetNumber.Value]:FindFirstChild("Offset").Value)
		ManipulationVariable = game:GetService("ReplicatedStorage").PlayerParts.EquippedPets['Pet'..Var2.PetNumber.Value]:FindFirstChild("Offset")
	end
end

if ManipulationVariable == nil then
	wait(3)
	for Var1, Var2 in pairs(RequirementsPetsFolder:GetChildren()) do
		if Var2:WaitForChild("PetNumber").Value ~= nil then
			print(Var2.PetNumber.Value)
			ManipulationVariable = game:GetService("ReplicatedStorage").PlayerParts.EquippedPets['Pet'..Var2.PetNumber.Value]:FindFirstChild("Offset")
		end
	end
end

game:GetService("RunService").RenderStepped:Connect(function()
	repeat wait() until ManipulationVariable.Value
	BodyPosition.Position = (Character.PrimaryPart.CFrame * CFrame.new(ManipulationVariable.Value.p.X, ManipulationVariable.Value.p.Y, ManipulationVariable.Value.p.Z)).p--CFrame.new(5, -1.8, 3)).p
	BodyGyro.CFrame = Character.PrimaryPart.CFrame
end)

^ Localscript inside the pet

local Camera = game.Workspace.CurrentCamera
local Studio = game.Workspace.Studio
local Player = game:GetService("Players").LocalPlayer

local Template = game:GetService("ReplicatedStorage"):WaitForChild("UI").Template
local ScrollingFrame = Player.PlayerGui.Inventory["Inventory Frame"].Inventory.ScrollingFrame

local CooldownClick = false

local function AddToFrame(Pet)
	local NewTemplate = Template:Clone()
	NewTemplate.Name = Pet.Name
	NewTemplate.Parent = ScrollingFrame
	
	local NewPet = game.ReplicatedStorage["Viewport Pets"][Pet.Name]:Clone()
	NewPet.Parent = NewTemplate.ViewportFrame
	
	local NewCamera = Instance.new("Camera")
	NewCamera.CFrame = CFrame.new(NewPet.PrimaryPart.Position + (NewPet.PrimaryPart.CFrame.lookVector * 2.25), NewPet.PrimaryPart.Position)
	NewCamera.Parent = NewTemplate.ViewportFrame
	
	NewTemplate.ViewportFrame.CurrentCamera = NewCamera
	
	NewTemplate.MouseButton1Click:Connect(function()	
		if NewTemplate.Equipped.Visible == true and CooldownClick == false then
			CooldownClick = true
			NewTemplate.Equipped.Visible = false
			game:GetService("ReplicatedStorage"):WaitForChild("Remotes").Unequip:FireServer(Pet.Name)
			wait(0.5)
			CooldownClick = false
		elseif Player.Stats.CurrentEquippedPets.Value < Player.Stats.MaxEquippedPets.Value and NewTemplate.Equipped.Visible == false and CooldownClick == false then
			CooldownClick = true
			NewTemplate.Equipped.Visible = true
			game:GetService("ReplicatedStorage"):WaitForChild("Remotes").Equip:FireServer(Pet.Name)
			wait(0.5)
			CooldownClick = false
		end
	end)
end

game:GetService("ReplicatedStorage"):WaitForChild("Remotes"):FindFirstChild("Hatch").OnClientEvent:Connect(function(Pet, Rarity)
	Player.PlayerGui.Inventory.CanToggle.Value = false
	if Player.PlayerGui.Inventory["Inventory Frame"].Visible == true then Player.PlayerGui.Inventory["Inventory Frame"].Visible = false end
	if Player.PlayerGui.Inventory["Equipped Frame"].Visible == true then Player.PlayerGui.Inventory["Equipped Frame"].Visible = false end

	AddToFrame(Pet)
	Studio["Egg Mesh"].Transparency = 0
	
	Camera.CameraType = Enum.CameraType.Scriptable
	Camera.CFrame = Studio.CameraPart.CFrame
	
	wait(1.5)
	
	Studio["Egg Mesh"].Transparency = 1
	
	local PetClone = Pet:Clone()
	
	for i,v in pairs(PetClone:GetChildren()) do
		if v:IsA("BasePart") then
			v.Anchored = true
		end
	end
	
	PetClone:SetPrimaryPartCFrame(CFrame.new(Studio["Egg Mesh"].Position, Studio.CameraPart.Position))
	PetClone.Parent = Studio
	
	Player.PlayerGui:FindFirstChild("Egg Hatching").Enabled = true
	Player.PlayerGui:FindFirstChild("Egg Hatching").Backing.TextLabel.Text = "You Got: "..Pet.Name..' ['..Rarity..']'
	
	local Tween = game:GetService("TweenService"):Create(Camera, TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, 0, false, 0), {CFrame = CFrame.new(PetClone.PrimaryPart.Position + (PetClone.PrimaryPart.CFrame.lookVector * 5) + Vector3.new(0,0.75,0), PetClone.PrimaryPart.Position)}):Play()	
	
	wait(2)
	
	Player.PlayerGui:FindFirstChild("Egg Hatching").Enabled = false
	Player.PlayerGui:FindFirstChild("Egg Hatching").Backing.TextLabel.Text = ''
	
	Camera.CameraType = Enum.CameraType.Custom
	Player.PlayerGui.Inventory.CanToggle.Value = true
	
	wait(0.1)
	PetClone:Destroy()
	
end)

wait(2)

AddToFrame(game.ReplicatedStorage.Pets['Black Pig'])
AddToFrame(game.ReplicatedStorage.Pets['Black Pig'])
AddToFrame(game.ReplicatedStorage.Pets['Red Pig'])
AddToFrame(game.ReplicatedStorage.Pets['Yellow Pig'])

^ Localscript controlling the GUI





^ Data structure

^ Problem

just check if there isn’t another pet at that position. Maybe you should make it one local script and have a table holding all the currently used positions.

1 Like

If you look at the most recent edit I uploaded a picture with the preset CFrame Offset’s, a table wouldn’t be any different.

If you read my scripts; I have been checking the pets positions with a variable called “PetNumber”