BasePart:ApplyImpulse() does not work on players

Problem

In trying to make a jump pad more consistent, I came across a problem with BasePart:ApplyImpulse(). It seems that no matter what I try, it will not work when used against a player’s character model. I even tried to change the humanoid state type to Physics which did nothing. Even task.wait() was inserted to make sure each part was executed in a different frame with the same results. I’m not sure if BasePart:ApplyImpulse() is broken for players or if there is something else that I need to do. I am using it against regular BaseParts which are not part of any player’s character and it seems to work fine for those. Furthermore, the documentation isn’t adequate since there’s no code examples and it does imply that it can be used on the player’s character model even when using a server script.

This issue occurs in both Studio and in a live game.


Additional Information

Field Value
Problem Area Engine
Problem Component Physics (Luau API)
First Noticed 23 Jan 2024
Impact Medium
Priority Medium
Annoyance Level Medium

It’s worth noting that directly setting the BasePart.AssemblyLinearVelocity directly will launch the player, but different values need to be calculated to achieve the same result. The documentation for this states that BasePart:ApplyImpulse() should be used “if you want instantaneous change in velocity.”


Visuals

Not really.


Expectations

What I expect to happen is that the impulse is applies to the player to launch them off the pad. With the given values, the player should be launched straight up and out of the game.


Reproduction

The steps to reproduce the issue are as follows:

  1. Load the repro file into Studio.
  2. Run it.
  3. Move the character to the jump pad.
  4. Observe the results (or lack there of).

Reproduction Files

Engine - ApplyImpulse.rbxl (53.3 KB)

10 Likes

You can run the root:ApplyImpulse(vector) on the client and it will work

Since the character is controlled by the client, the :ApplyImpulse does not have any effects on it from a server script. Not sure why it doesn’t replicate however remote events can fix that for you.

Here is an updated script you can use to test:

--[[

Created by Maelstorm_1973
Copyright (C)2024 Dracolynxis Technologies Inc.

Jump Pad Script

--]]



local pad = workspace:WaitForChild("JumpPad")
local jumpVector = pad:GetAttribute("JumpVector")
local debounce = false
local refMass = .05


local function getCharParts(part)
	local char = part:FindFirstAncestorOfClass("Model")
	if char ~= nil then
		local human = char:FindFirstChild("Humanoid")
		local root = char:FindFirstChild("HumanoidRootPart")
		return char, human, root
	end
	return nil
end



pad.Touched:Connect(function(part)
	if debounce == false then
		debounce = true

		local char, human, root = getCharParts(part)
		if char == nil then
			debounce = false
			return
		end

		local mass = root.AssemblyMass / refMass
		local vector = jumpVector * refMass
		print(vector)

		root:ApplyImpulse(vector)
		task.delay(0.1, function()
			debounce = false
		end)
	end
end)

Put this script in a local script under StarterGui.

3 Likes

@arxweb is correct. This issue just boils down to network ownership. The server isn’t responsible for simulating the player so applying an impulse on the server does nothing. Switching the RunContext for the script under the JumpPad to Client seems to give the expected behavior.

3 Likes

The documentation should be updated to reflect this. I was going crazy trying to figure out why this wouldn’t work for players when it worked for parts.

1 Like

I’ve had inconsistency with physics objects or methods like this one. It especially hardly works on players who are standing on the ground. Yes, even when done on the client on their own character.

https://devforum.roblox.com/t/how-well-have-physics-constraints-worked-for-you/2571543/16

BodyVelocities are much better for this, and if that’s your issue, you should consider using BodyVelocities to move your character.

BodyVelocity is deprecated, maybe LinearVelocity?

Trying to make a jump pad that doesn’t use Humanoid.Jump = true to launch off the pad. The problem with that is in my game, the jump power can change for the player, so if they have a jump powerup, they will go much further than intended. So to launch, I’m forced to use HumanoidRootPart.AssemblyLinearVelocity to get them off the pad then VectorForce for about 1 second to get them the rest of the way on inertia. So the whole thing with apply impulse would be nice if it was on the server.

Running this on the client is better because the user should have immediate feedback for this action. This is not a matter of client security, as clients can already walk themselves through thin air if they have the means to do so. Putting the jump action on the client is harmless, better for feeling, and generally recommended. Everything for player movement is mostly.

The physics seems much more consistent with the new ControllerManagers, I think regular Humanoids run their own, custom physics simulation which makes it very difficult for the normal one to apply any forces to it.

EDIT: Woah, actually, the example state machine script uses :ApplyImpulse!

-- Jump input
local function doJump(actionName, inputState, inputObject)
	if inputState == Enum.UserInputState.Begin and isControllerActive(cm.GroundController) then
		local jumpImpulse = cm:GetAttribute("JumpImpulse")
		cm.RootPart:ApplyImpulse(jumpImpulse) <--- HERE
		
		character.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
		cm.ActiveController = cm.AirController

cc: @Maelstorm_1973 You will probably have a much easier time implementing any physics mechanics in your game if you use ControllerManagers, they are based entirely on the existing physics engine.

2 Likes

It does seem to work on the client when using HumanoidRootPart:ApplyImpulse() to the player. So network ownership is the issue. Humanoid.Jump = true can be done on the server. There’s a couple of other things I’m going to try with this.

I could not even figure out how to set this up. The player would not be able to walk correctly, they fall over, glitch, etc. Are you sure this is easier??

It’s much more customizable, and you have much more control. Did you use the example scripts? They should set everything up, disable the default humanoid, and then start controlling the ControllerManager.

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