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:
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)
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
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)
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)
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
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)
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)
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)