Need help with Crouch System

Hello Developers :wave:

Context

I am creating a crouch system for my game.
It is a Hold [Button] to Crouch type.

Issue

Everything works fine, but the problem here is that whenever the players gets out of a place (let’s say a vent of sorts), the player still remains crouching (even if the button is not being pressed). And only gets up if the player pressed the button again.

What I want

I want the player to automatically uncrouch once they get out of the place if they are not holding the crouch button.

Media

Code

--!strict
local ContextActionService = game:GetService("ContextActionService");
local RunService = game:GetService("RunService");

local GeometricPlane = Vector3.new(1, 0, 1);
local UpVector = Vector3.new(0, 1, 0);

local States = {
	["Crouching"] = Instance.new("BoolValue");
};

local player = game.Players.LocalPlayer;
local character = player.Character or player.CharacterAdded:Wait();

local Humanoid = character:WaitForChild("Humanoid") :: Humanoid;
local Animator = Humanoid:WaitForChild("Animator") :: Animator;
local HumanoidRootPart = Humanoid.RootPart :: BasePart;

local AnimationFolder = script:WaitForChild("Animations");
local Animations = {} :: {[string]: AnimationTrack}

for i: number, v: Animation in ipairs(AnimationFolder:GetChildren()) do
	if v:IsA("Animation") then
		Animations[v.Name] = Animator:LoadAnimation(v);
		Animations[v.Name].Priority = Enum.AnimationPriority.Action2;
	end;
end;

local WalkSpeed = Humanoid.WalkSpeed;
local CrouchSpeed = WalkSpeed/2;

local range = 2;

function isBelowAnObject(character: Model, range: number): (boolean?)
	local RParams = RaycastParams.new()
	RParams.FilterType = Enum.RaycastFilterType.Exclude;
	RParams.IgnoreWater = true;
	RParams.RespectCanCollide = true;
	RParams.FilterDescendantsInstances = {character};
	
	local result = workspace:Raycast(HumanoidRootPart.Position, UpVector * range, RParams);
	
	if (result) then
		if (result.Instance ~= nil) then
			return (true);
		end;
	end;
	
	return (false);
end;

function Crouch(ActionName: string, InputState: Enum.UserInputState, InputObject: InputObject): ()
	if (ActionName == "CrouchPlayer") then
		if (InputState == Enum.UserInputState.Begin) then
			States["Crouching"].Value = true;
		end;
		if (InputState == Enum.UserInputState.End) then
			if (not isBelowAnObject(character, range)) then
				States["Crouching"].Value = false;
			else
				return;
			end;
		end;
	end;
end;

States["Crouching"]:GetPropertyChangedSignal("Value"):Connect(function()
	local Value = States["Crouching"].Value;
	
	RunService.Heartbeat:Connect(function(dt: number)
		if (Humanoid.MoveDirection.Magnitude > 0) then
			Animations["Crouch"]:AdjustSpeed(1);
		else
			Animations["Crouch"]:AdjustSpeed(0);
		end;
	end);
	
	if (Value) then
		Animations["Crouch"]:Play();
		Humanoid.WalkSpeed = CrouchSpeed;
	else
		Animations["Crouch"]:Stop()
		Humanoid.WalkSpeed = WalkSpeed;
	end;
end);

ContextActionService:BindAction("CrouchPlayer", Crouch, true, Enum.KeyCode.C, Enum.KeyCode.LeftShift, Enum.KeyCode.LeftControl);

I believe that I have made some sort of error in the crouch function regarding the logic and control flow.
Please help me rectify it.
Thank you :smiling_face:

2 Likes

You need to constantly check if the player is below something in case they release crouch under an object. As of right now, you only check it once and not again until you press and release C.

1 Like

Thank you!

Updated Crouch Function

function Crouch(ActionName: string, InputState: Enum.UserInputState, InputObject: InputObject): ()
	if (ActionName == "CrouchPlayer") then
		if (InputState == Enum.UserInputState.Begin) then
			States["Crouching"].Value = true;
			if CrouchConnection then
				CrouchConnection:Disconnect();
			end;
		end;
		if (InputState == Enum.UserInputState.End) then
			CrouchConnection = RunService.Heartbeat:Connect(function(dt: number)
				if (not isBelowAnObject(character, range)) then
					States["Crouching"].Value = false;
				end;
			end);
		end;
	end;
end;
3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.