Pet follower issue

Hello, I have been working on a pet follower script like pet simulator X and I need the pet to walk perfectly on top of the floor, but it clips through parts that are taller than it:


image


Here is my code:

local pet = workspace.Pet
local character = script.Parent

game:GetService("RunService").RenderStepped:Connect(function()
	local rayOrigin = Vector3.new(pet.PrimaryPart.Position.X,pet.PrimaryPart.Position.Y , pet.PrimaryPart.Position.Z)
	local direction = Vector3.new(0, -1, 0)*100
	
	local ray = workspace:Raycast(rayOrigin, direction)
	
	if ray then
		pet:SetPrimaryPartCFrame(CFrame.new(Vector3.new(character.PrimaryPart.Position.X + 5,ray.Position.Y+ pet.PrimaryPart.Size.Y/2,character.PrimaryPart.Position.Z+5)))
		
	end
end)

Thank you!

I also only want it to climb parts that are a certain size (So that it does not go over trees and stuff).

You’re only making the pet be at the surface level of the part
pet.PrimaryPart.Size.Y/2
You also need to include the pets actual size,
via Model:GetExtentsSize
If you dont want it to go over certain things then just blacklist them that way it will never consider repositioning, and make sure its a different collission group so it can go through walls without issue

1 Like

How can I use Model:GetExtentsSize with this?
I tried this but it errors:

game:GetService("RunService").RenderStepped:Connect(function()
	local rayOrigin = Vector3.new(pet.PrimaryPart.Position.X,pet.PrimaryPart.Position.Y , pet.PrimaryPart.Position.Z)
	local direction = Vector3.new(0, -1, 0)*100
	
	local ray = workspace:Raycast(rayOrigin, direction)
	
	if ray then
		pet:SetPrimaryPartCFrame(CFrame.new(Vector3.new(character.PrimaryPart.Position.X + 5,ray.Position.Y+ pet:GetExtentsSize(),character.PrimaryPart.Position.Z+5)))
		
	end

end)


getextenssize returns a Vector3, you would need to do pet:GetExtensize().Y or define a variable and do myVar.Y

1 Like

When I do that it works but it doesn’t position it exactly on top of the surface that its touching:

local pet = workspace.Pet
local character = script.Parent

game:GetService("RunService").RenderStepped:Connect(function()
	local rayOrigin = Vector3.new(pet.PrimaryPart.Position.X,pet.PrimaryPart.Position.Y , pet.PrimaryPart.Position.Z)
	local direction = Vector3.new(0, -1, 0)*100
	
	local ray = workspace:Raycast(rayOrigin, direction)
	
	if ray then
		pet:SetPrimaryPartCFrame(CFrame.new(Vector3.new(character.PrimaryPart.Position.X + 5,ray.Position.Y+ pet:GetExtentsSize().Y,character.PrimaryPart.Position.Z+5)))
		
	end
end)

Your Y axis calculation should be like the following:

ray.Instance.Size.Y + ray.Instance.Size.Y/2 + pet:GetExtentsSize().Y

Dividing instance size by 2 gets you an increase of half the size, The vector3 will always start from dead centre so we first want to reach the “top” of the instance, Once we’ve done this we just need to apply our Models absolute Y size which will make it always perfectly align on top

1 Like

I tried it but this happens:

local pet = workspace.Pet
local character = script.Parent

game:GetService("RunService").RenderStepped:Connect(function()
	local rayOrigin = Vector3.new(pet.PrimaryPart.Position.X,pet.PrimaryPart.Position.Y , pet.PrimaryPart.Position.Z)
	local direction = Vector3.new(0, -1, 0)*100
	
	local ray = workspace:Raycast(rayOrigin, direction)
	
	if ray then
		pet:SetPrimaryPartCFrame(CFrame.new(Vector3.new(character.PrimaryPart.Position.X + 5,ray.Instance.Size.Y + ray.Instance.Size.Y/2 + pet:GetExtentsSize().Y,character.PrimaryPart.Position.Z+5)))
		
	end
end)
1 Like

The issue with raycasting from the position of the pet to the floor is that it won’t detect any parts above half the height of the pet. So to fix this issue, you just simply add the y axis offset vector to the origin vector.


The first figure fails to check the top half of its size, while the second figure is offsetting upwards (orange line) from the origin to check for parts the whole way down.

Here is the fixed code.

local RunService = game:GetService('RunService');

local pet = workspace.Pet;
local character = script.Parent;

local params = RaycastParams.new();
params.FilterType = Enum.RaycastFilterType.Blacklist;
params.FilterDescendantsInstances = {pet};

local detectRange = 4;

RunService.RenderStepped:Connect(function()
	local rayOrigin = pet.PrimaryPart.Position + (Vector3.yAxis * (detectRange + pet.Size.Y/2));
	local direction = -Vector3.yAxis * 100;

	local result = workspace:Raycast(rayOrigin, direction);

	if result then
		pet:SetPrimaryPartCFrame(CFrame.new(
			character.PrimaryPart.Position.X + 5,
			result.Position.Y + pet.PrimaryPart.Size.Y/2,
			character.PrimaryPart.Position.Z + 5
			)
		);
	end
end)
1 Like

Thank you! After raycasting from the top of the pet it worked but I am also trying to make it always follow the character from behind but this happens:


Here is my code:

local pet = workspace.Pet
local character = script.Parent

game:GetService("RunService").RenderStepped:Connect(function()
	local rayOrigin = Vector3.new(pet.PrimaryPart.Position.X, pet.PrimaryPart.Position.Y + 20 , pet.PrimaryPart.Position.Z)
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {pet}
	params.FilterType = Enum.RaycastFilterType.Blacklist
	
	local direction = Vector3.new(0, -1, 0)*100

	local ray = workspace:Raycast(rayOrigin, direction, params)

	if ray then
		pet:SetPrimaryPartCFrame(CFrame.new(character.PrimaryPart.CFrame.X + 5,ray.Position.Y+ pet.PrimaryPart.Size.Y/2,character.PrimaryPart.CFrame.Z+5))

	end
end)

Thank you!

You should really try to use attachments and AlignPosition for this :)!

1 Like
		local copyPet = game.ReplicatedStorage.PetsModel[v.Type]:Clone()
		setNetworkOwnerOfModel(copyPet, Character)

		copyPet.Name = v.Id
		copyPet.Parent = workspace.Pets.att
		copyPet:SetPrimaryPartCFrame(Character["HumanoidRootPart"].CFrame)

		local ac = Instance.new("Attachment",Character["HumanoidRootPart"])
		ac.Visible = false
		ac.Name = "ACharacter-"..v.Id

		if SubI > 3 then
			SubI = 1
		end

		local Row = math.ceil(i/3)
		ac.Position = Vector3.new(-8 + (4*SubI), 0 ,(4*Row)+4)

		local ap = Instance.new("Attachment", copyPet.PrimaryPart)
		ap.Visible = false
		ap.Name = "APet"

		local alignPosition = Instance.new("AlignPosition")
		alignPosition.MaxForce = 25000
		alignPosition.Attachment0 = ap
		alignPosition.Attachment1 = ac
		alignPosition.Responsiveness = 25
		alignPosition.Parent = copyPet

		local alignOrientation = Instance.new("AlignOrientation")
		alignOrientation.MaxTorque = 25000
		alignOrientation.Attachment0 = ap
		alignOrientation.Attachment1 = ac
		alignOrientation.Responsiveness = 25
		alignOrientation.Parent = copyPet

		SubI += 1
		wait(0.2)
	end