Get part instance a humanoid is standing on

I have a basic physic grabbing system, however, one problem I have is that player are able to abuse the grab by standing on top of their grabbed object and float with it.
If I am able to detect what the humanoid is standing on, I should be able to force player to let go of said object.

Is there an API where I can get what the humanoid is standing on?
My other idea if this can’t be solved easily is to disable the object’s collision with the player grabbing the object or using shapecast.

Edit: I have decided to go with disabling the object’s collision method

2 Likes

I believe you can do this:

if humanoid.FloorMaterial ~= Enum.Material.Air then
    on_floor = true -- They are standing on the floor
else
    on_floor = false -- They are standing on the object
end

I think this could work. I am not sure how accurate it is, but in theory if the humanoid’s floor material was air they would be standing on top of something that isn’t the floor.

1 Like

The problem with that is that the humanoid will detect the material of the object the player is grabbing and standing on.
And also this will cause player to let go of the prop when they jump or go mid air accidentally, which I want to avoid.

1 Like

Maybe try detecting if the player is touching the object? I don’t know if CanTouch is enabled or not, but if the player is touching the object then the player would be on the object.

EDIT: Once you pick up the object, you could then disable CanTouch.
EDIT2: Use this instead:

2 Likes

That was one of the solution I had in my head but it was quickly shut down by the fact that some object are just big enough to slightly touch the player when moving it around and cause it to drop unintentionally when it bump the player.

1 Like

You could use create an object hitbox around each object that is slightly bigger than the object itself every time it is grabbed. However, I’m not sure how effective it would be.

1 Like

I would say that using part.Touched is your best option here. Then after the event is fired, just use RayCast to shoot a ray straight down from the HumanoidRootPart to see if it is below the character. If it is, then you can stop the grab functions. If it isn’t then you can continue.

Small problem with this is that the object wouldn’t necessarily be directly below the hrp, so if it is slightly offset, it may not work. However, this is a very rare case. Additionally since OP already has a loop to move the object, I think that using GetPartsInPart() would work better for them if they were to use a hitbox based system.

1 Like

The hitbox would be on top of the object then?

Something like:

local part = -- Path to part
local hitbox = Instance.new("Part", part)

hitbox.Size = Vector3.new(part.Size.X, 1, part.Size.Z)
hitbox.CFrame = part.CFrame + CFrame.new(0, part.Size.Y, 0)

hitbox.CanCollide = false
hitbox.CanTouch = true
hitbox.Transparency = 1

hitbox.Touched:Connect(function(hit)
    -- Test for player, etc.
end)

This may not work because the object may be rotated. The hitbox could be adjusted each frame to hover slightly above the object.

1 Like

So something like this:

local run_service = game:GetService("RunService")

local part = -- Path to part
local hitbox = Instance.new("Part", part)

hitbox.CanCollide = false
hitbox.CanTouch = true
hitbox.Transparency = 1

hitbox.Size = Vector3.new(part.Size.X, 1, part.Size.Z)

-- Assuming this is running on the server
run_service.Hearbeat:Connect(function()
    hitbox.CFrame = part.CFrame + CFrame.new(0, part.Size.Y, 0)
end)

hitbox.Touched:Connect(function(hit)
    -- Test for player, etc.
end)

It would probably be more like this. You could also do more checks to make sure 100% they are bug abusing.

Edit: Added Height Check

local run_service = game:GetService("RunService")

local part = -- Path to part
local hitbox = Instance.new("Part", part)

hitbox.CanCollide = false
hitbox.CanTouch = true
hitbox.Transparency = 1

hitbox.Size = Vector3.new(part.Size.X, 1, part.Size.Z)

-- Assuming this is running on the server
run_service.Hearbeat:Connect(function()
    hitbox.CFrame = part.CFrame + CFrame.new(0, part.Size.Y + 1, 0) -- Mitigate chances of false report
    if table.find(workspace:GetPartsInPart(hitbox), hrp)  and hrp.Position.Y > hitbox.Position.Y then -- Assumes HRP is defined
        -- Quit holding
    end
end)
1 Like