Limiting Velocity for the Player when touching a Union

Hi! I’m trying to make a cobweb similar to Minecraft for a Halloween event in my game, I’m trying to limit the player’s velocity so they get slowed down in all directions when touching a union.

Whenever the user enters the cobweb, the script only seems to partially work. The player’s velocity is only partially limited, for example, jumping into the union from below, the script doesn’t limit it as much as I want to, and lowering the limitValue doesn’t seem to have an effect. Moving in all three directions makes the effect even more unreliable. I want it to work in all circumstances since my game is a world builder that allows players to place these anywhere they want.

I’ve tried this on the server and the client, and it seems to work more reliably on the server, but the limit value appears to be basically ignored unless it’s a higher number.

The union is anchored and has CanCollide off, and CanQuery and CanTouch on

local RunService = game:GetService("RunService")

function LimitVelocity(Velocity)
	local x = Velocity.z
	local y = Velocity.y
	local z = Velocity.z
	
	local limit = .25
	
	if y < limit then
		y = limit
	elseif y > -limit then
		y = -limit
	end
	if x < limit then
		x = limit
	elseif x > -limit then
		x = -limit
	end
	if z < limit then
		z = limit
	elseif z > -limit then
		z = -limit
	end
	
	return Vector3.new(x, y, z)
end


RunService.Heartbeat:Connect(function()
	local parts = workspace:GetPartsInPart(script.Parent)
	for i, value in ipairs(parts) do
		if value.Parent:FindFirstChildWhichIsA("Humanoid") and value.Parent.PrimaryPart.Name == "HumanoidRootPart" then
			value.Parent.PrimaryPart.AssemblyLinearVelocity = LimitVelocity(value.Parent.PrimaryPart.AssemblyLinearVelocity)
			print(value.Parent.PrimaryPart.AssemblyLinearVelocity)
		end
	end
end)

Here is also the union (model) I’m using, I tested it on a normal box, and it seems to do the same thing.

I’d greatly appreciate it if anyone had a fix for my problem, thank you!

1 Like

When the player first enters the cobweb, you can simply grab their mass and slow them down using a couple tricks:

Firstly, you can slow down their walk speed, which will control horizontal speed.
For vertical speed, you can apply an upward force to their character as they are falling (similar to cobwebs in Minecraft). The best approach from what I have seen is to use a VectorForce. In this case, it should go on the HumanoidRootPart.

The VectorForce will apply a continuous force of specified scale to a given physics body. You can simply adjust the effect to get the desired speed you want the player to fall or slow down at when walking in the cobwebs:

The Module I used below is ZonePlus: ZonePlus v3.2.0 | Construct dynamic zones and effectively determine players and parts within their boundaries

local Zone = require(game:GetService("ReplicatedStorage"):WaitForChild("Zone"))
local Cobweb = Zone.new(workspace.Cobweb)

local playersInCobweb = {}

local COBWEB_GRAVITY = 0.35

local function getCharacterMass(character: Model): any
    if character then
        local mass
        for _, part in pairs(character) do
            if part:IsA("BasePart") then
                mass += part:GetMass()
            end
        end
        return mass
    end
end

local function SlowdownPlayer(player: Player)
    if player then
        local character = player.Character
        if character then
            local HRP = character.HumanoidRootPart
            if HRP then
                local characterMass = getCharacterMass(character)
                local vf = Instance.new("VectorForce")
                vf.Parent = HRP
                vf.Attachment0 = HRP.RootAttachment
                vf.RelativeTo = Enum.ActuatorRelativeTo.World
                vf.Force = Vector3.new(
                    0,
                    (characterMass * workspace.Gravity) * COBWEB_GRAVITY,
                    0
                )
                return vf
            end
        end
    end
end

Cobweb.playerEntered:Connect(function(player)
    if player then
        local character = player.Character
        if character then
            local humanoid = character:FindFirstChild("Humanoid")
            if humanoid then
                humanoid.WalkSpeed = 10
                playersInCobweb[player] = SlowdownPlayer(player)
            end
        end
    end
end)

Cobweb.playerExited:Connect(function(player)
    if player and playersInCobweb[player] then
        local character = player.Character
        if character then
            local humanoid = character:FindFirstChild("Humanoid")
            if humanoid then
                humanoid.WalkSpeed = 16 -- Change to other, if desired
            end
        end
        playersInCobweb[player]:Destroy()
    end
end)
1 Like

Correct me if I’m wrong, but is it not easier to set the walkspeed and jumpheight values of the humanoid whenever the cobweb touches the part of a player?

Edit: Nevermind, this only takes effect on the X and Z axis, not Y.

I tried to use the script, and even after some changes (the original script didn’t work due to errors, but I tried my best to fix it), it seems that when entering and leaving a part, Zone doesn’t register fast enough, and the results are delayed, so I’m getting very unexpected results when jumping into it from under like this.


Other things I’ve experienced is when falling into the cobweb from above if going fast enough, then the cobweb doesn’t have any effect, and also when walking into the cobweb, it takes about a second or two to start the script

Here is the edited code I used:

local Zone = require(game:GetService("ReplicatedStorage"):WaitForChild("Zone"))
local Cobweb = Zone.new(script.Parent)

local playersInCobweb = {}

local COBWEB_GRAVITY = 16.5

local function getCharacterMass(character: Model): any
	if character then
		local mass
		
		for _, part in pairs(character:GetChildren()) do
			if part:IsA("BasePart") then
				mass = part:GetMass()
			end
		end
		return mass
	end
end

local function SlowdownPlayer(player: Player)
	if player then
		local character = player.Character
		if character then
			local HRP = character.HumanoidRootPart
			if HRP then
				local characterMass = getCharacterMass(character)
				local vf = Instance.new("VectorForce")
				vf.Parent = HRP
				vf.Attachment0 = HRP.RootAttachment
				vf.RelativeTo = Enum.ActuatorRelativeTo.World
				vf.Force = Vector3.new(
					0,
					((characterMass * workspace.Gravity) * COBWEB_GRAVITY),
					0
				)
				print(vf.Force)
				return vf
			end
		end
	end
end

Cobweb.playerEntered:Connect(function(player)
	if player then
		local character = player.Character
		if character then
			local humanoid = character:FindFirstChild("Humanoid")
			if humanoid then
				humanoid.WalkSpeed = 4
				playersInCobweb[player] = SlowdownPlayer(player)
			end
		end
	end
end)

Cobweb.playerExited:Connect(function(player)
	if player and playersInCobweb[player] then
		local character = player.Character
		if character then
			local humanoid = character:FindFirstChild("Humanoid")
			if humanoid then
				humanoid.WalkSpeed = 16 -- Change to other, if desired
			end
		end
		playersInCobweb[player]:Destroy()
	end
end)

I also used the latest version of Zone from GitHub.