Help With PetFollow Script

I’m trying to update my Script so that the pets don’t enter the walls, I wanted them to float on top of the block when it occupies the place where the pet would normally be, here’s how my script looks now:

as you can the pet can stay on top of the block, however it only stays on top of the first block that is inside if you activate another one on top the pet will stay inside.

Here is my code:


function GetPos (Part,partPositionBase,PetsFolder)
	local bodyPos
	
	
	local CF,ModelSize = Part:FindFirstAncestorOfClass("Model"):GetBoundingBox()
	
	local Float = 1
	
	local MaxToUp = 15
	
	local PosNow = ModelSize.Y/2
	
	local RegionWithModel = Region3.new(partPositionBase - ModelSize/2, partPositionBase + ModelSize/2)

	local overlappingParts = game.Workspace:FindPartsInRegion3(RegionWithModel, PetsFolder, 20)
	
	for i,v in pairs(overlappingParts) do
		if v.CanCollide and v.Transparency < 1  then
			local NewPos = ((overlappingParts[1].Position.Y + overlappingParts[1].Size.Y/2) - partPositionBase.Y) + Float + ModelSize.Y/2
			
			if (NewPos) >= MaxToUp then
				PosNow = NewPos
				break
			elseif NewPos > PosNow then
				PosNow = NewPos
			end
		end
	end
	
	bodyPos = Vector3.new(0, PosNow, 0)
	
	if #overlappingParts < 1 then
		
		local ray = Ray.new(partPositionBase, Vector3.new(0, -MaxToUp, 0))
		local hit, pos = game.Workspace:FindPartOnRayWithIgnoreList(ray, {PetsFolder})
		
		local Difernece = 	hit and (partPositionBase.Y-(pos.Y + Float)) or 0
		
		if Difernece > MaxToUp then Difernece = MaxToUp end
		
		if hit and (pos.Y + Float) < partPositionBase.Y and Difernece > 0  then
			bodyPos = Vector3.new(0,-Difernece+ModelSize.Y/2,0)
		else
			bodyPos = Vector3.new(0,ModelSize.Y/2,0)
		end
	end
	return bodyPos
end

while true do
	for i,PlayerFolder in pairs(workspace.PlayerPets:GetChildren()) do
		--coroutine.wrap(function()
		local Player = game.Players:FindFirstChild(PlayerFolder.Name)
		if Player then
			local PlayerChar = Player.Character or Player.CharacterAdded:Wait()
			local Root = PlayerChar:FindFirstChild("HumanoidRootPart")

			for i,Pet in pairs(PlayerFolder:GetChildren()) do
				if Root then
					local Pos = Pet.Pos.Value  --  Position on a circular radius
					local BG = Pet.PrimaryPart.BodyGyro
					local BP = Pet.PrimaryPart.BodyPosition
					local d = Root.Position.Y - Pet.PrimaryPart.Position.Y

					local PosNew = GetPos(Pet.PrimaryPart, (Root.Position + Pos),PlayerFolder)
					
					BP.Position = (Root.Position + PosNew + Pos) + Vector3.new(0,game.ServerScriptService.ScriptsPetSystem.globalPetFloat.Value,0)

					if Player.DataPlayer.isWalking.Value == false then
						BG.CFrame = CFrame.new(Pet.PrimaryPart.Position, Root.Position - Vector3.new(0, d, 0))
					else
						BG.CFrame = Root.CFrame
					end
				end
			end

			wait()
		else
			PlayerFolder:Destroy()
		end
		--end)()
	end
	game:GetService("RunService").Heartbeat:Wait()
end

1 Like

I believe raycasting would be a better solution.

I thought about it but I couldn’t make a code able to work correctly

You can use workspace:Raycast() and raycast downwards from a position above the pet. Or, you can use workspace:GetPartsInPart because the region 3 functions are deprecated.