Recreating Minecraft Sneak System

  1. I’m trying to recreate a sneaking system similar to the one in Minecraft.

  2. Sometimes the walk speed becomes 16 even though I’m still standing at the edge. It keeps switching between 16 and 0 for a few seconds, causing the player to slip off the block and fall.

  3. I’ve tried a few approaches, but none of them worked the way I wanted.
    In Minecraft, sneaking lets you stand exactly at the edge of a block without falling, and that’s what I’m trying to replicate.
    Code:

local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer

local Raycast = RaycastParams.new()
Raycast.FilterDescendantsInstances = {LocalPlayer.Character}
Raycast.FilterType = Enum.RaycastFilterType.Exclude
while task.wait() do
	local Result = workspace:Raycast(LocalPlayer.Character.PrimaryPart.Position, Vector3.new(0, -6, 0), Raycast)
	if not Result then			
		LocalPlayer.Character:FindFirstChildOfClass("Humanoid").WalkSpeed = 0
	else
		LocalPlayer.Character:FindFirstChildOfClass("Humanoid").WalkSpeed = 16
	end
end
1 Like

This might not solve exactly what your problem is here, but you’d probably want to raycast in a few points downward around the character instead of directly below the centre of their root part, for better accuracy.

2 Likes

Your current system makes it so that once the character is near to an edge, it sets the WalkSpeed to 0 and causes your character to stuck, unable to go back to their original speed earlier.

In Minecraft, there’s a a designated key that toggles the crouching system. When the key is pressed, the WalkSpeed decreases, and, when the character is near the edge, it still allows the player to walk but not fall.

You should use a service that handles the player’s input like UserInputService. To detect whether a player is near the edge, you should reposition the raycast origin position in front of the character accouting for its position and orientation. If it hits nothing then it’s most likely your character is near an edge. You’d have to figure out how to make it so that the character continues to walk but not go over the edge to prevent them from falling. My current idea is to use collision groups and filtering to setup an invisble wall that collides with anyone that is near the edge.

2 Likes
local char = script.Parent
local hmr: BasePart = char:WaitForChild("HumanoidRootPart")
local hmn: Humanoid = char:WaitForChild("Humanoid")
local _, size = char:GetBoundingBox()

local runService = game:GetService("RunService")

local red = Instance.new("Part", workspace)
red.Size = vector.one
red.BrickColor = BrickColor.Red()
red.Anchored = true
red.CanCollide = false

local yellow = Instance.new("Part", workspace)
yellow.Size = vector.one
yellow.BrickColor = BrickColor.Yellow()
yellow.Anchored = true
yellow.CanCollide = false

local green = Instance.new("Part", workspace)
green.Size = vector.one
green.BrickColor = BrickColor.Green()
green.Anchored = true
green.CanCollide = false

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {char, red, yellow, green}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude

runService.Heartbeat:Connect(function()
    local moveDir = hmn.MoveDirection
    if hmn.FloorMaterial == Enum.Material.Air then
        return
    end
    
    if moveDir.Magnitude < 0.1 then
        hmn.WalkSpeed = 16
        return
    end

    --// cast point a bit in front of the character
    local forwardPos = hmr.Position + moveDir 
    local rayOrigin = forwardPos
    local rayDirection = vector.create(0, -size.Y / 2 - 0.5, 0)
    
    green.Position = rayOrigin
    yellow.Position = rayOrigin + rayDirection

    local result = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

    if not result or not result.Instance then
        --// no ground ahead -> stop movement
        hmn.WalkSpeed = 0
    else
        red.Position = result.Position
        hmn.WalkSpeed = 16
    end
end)

this should work, those parts are for visuals to see if everything is correct

btw this should work good cause im using MoveDirection so even if you are at the edge facing forwards but holding S, it will let u go back to ur old position