How would I get the horizontal velocity of a basepart in object space?

So here’s my issue; I need to get the horizontal velocity of my character’s rootpart in object space, and I’m having issues with it. Here’s an image of what I’m trying to achieve:

The green line is what I want to achieve, and the red visualisation is the rootpart’s AssemblyLinearVelocity.

Currently the script is set up to use the rootpart’s AssemblyLinearVelocity to determine its top speed (yes the lack of a speed cap is intentional) which works fine for the most part, but causes issues when slamming into the ground as it just checks its magnitude and allows massive speeds when falling from a height.

To fix it I’m trying to get something similar to Vector3.new(velocity.X, 0, velocity.Z) but relative to the rootpart’s CFrame.UpVector to determine the player’s speed instead (as the aforementioned method causes issues when running up walls and over terrain).

Any help would be appreciated, I’ll check any responses in the morning as it’s 12am here.

1 Like

I am not sure if my math is correct, but try this:

local velocity = humanoidRootPart.AssemblyLinearVelocity
local lookVector = humanoidRootPart.CFrame.LookVector
local lookVelocity = velocity:Dot(lookVector)

Where lookVelocity is the velocity in the green direction

I probably should’ve provided more information, here’s the formula for the controllermanager’s speed:

--in function binded to render step
velocity = body.rootPart.AssemblyLinearVelocity
local horizontalVelocity = velocity --set as a placeholder
ctManager.BaseMoveSpeed = 
	if ctManager.MovingDirection.Magnitude > 0 then
		(horizontalVelocity.Magnitude + (ctManager.MovingDirection.Magnitude * 3) * speedMulti) * thumbstickPos
	else 1
--[[notes:
horizontalVelocity is currently set to rootpart's AssemblyLinearVelocity
speedMulti is always 0.25 right now
thumbstickPos is usually 1 and clamped between 0 and 1 and is determined by how far out a thumbstick is if connected, otherwise returns 1
]]--

The HumanoidRootPart always faces upwards to support the code that allows running on walls, and I’m trying to get the velocity in object space but also removing its y component.

Here’s some examples of what I’ve tried (red line is horizontalVelocity, videos may be a bit grainy since they’re compressed from about 50mb+ to like 8):

  • horizontalVelocity = velocity (current behaviour, you can go over terrain and run up walls fine, but you can hit the ground at a high speed and immediately gain momentum):

  • horizontalVelocity = Vector3.new(velocity.X, 0, velocity.Z) (this fixes the speed issue but breaks running when player isn’t facing directly up):

  • horizontalVelocity = velocity:Dot(body.lowerTorso.CFrame.LookVector) (no clue how to visualise this one properly but it doesn’t really work)

Try

local relativeVelocity = body.lowerTorso.CFrame.Rotation:PointToObjectSpace(body.rootPart.AssemblyLinearVelocity)
horizontalVelocity = Vector3.new(relativeVelocity.X, 0, relativeVelocity.Z)

Theoretically, this should work.

I think i may understand what you want now. I thought you only wanted the velocity in the forward direction of the player. Try this instead:

local velocity = rootPart.AssemblyLinearVelocity
local rpCF = rootPart.CFrame
local lookVelocity = velocity:Dot(rpCF.LookVector)
local rightVelocity = velocity:Dot(rpCF.RightVector)
local horizontalVelocity = Vector2.new(rightVelocity, lookVelocity)

This should account for movement to the left and right side, which my previous response did not. To get the velocity as a single number, you can just do:
horizontalVelocity.Magnitude
Also, i don’t know if this helps, but i made a sketch that is meant to show the values you would get from horizontalVelocity after moving in certain directions:

The code i provided depends on that the fact that the Root Parts orientation hasn’t been changed, so to make the code work for your case, you might need to adjust which directions are forward and right.

Edit:
I also noticed you used the LookVector from the lower torso before. I think it might be better to use the HumanoidRootPart as the reference instead if possible, as it is stabilized, which the other bodyparts are not. (Unless you coded them to be of course)

1 Like

this works pretty much perfectly, i’ll have to adjust other scripts but the code does exactly what i expected, thanks for the help

1 Like

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