If I understand your question, you’re looking for a Vector3 (we’ll call it “dampingV3”) such that:
dampedVelocity = dampingV3 * originalVelocity
Is this correct?
If so, the solutions for dampingV3 only exist** for the 6 cardinal directions of gravity (1,0,0), (0,1,0), (0,0,1),(-1,0,0), etc. and they are the trivial solutions you get just from replacing all the zeroes with your damping constant.
**only exist as Vector3. There is a solution for all velocities if you allow the damping multiplier to be a 3x3 matrix instead of a vector3, which could be implemented as an ‘illegal’ (non-orthogonal) CFrame. But I’m going to skip that, because there’s a simpler way.
But… for arbitrary directions of gravity, this doesn’t work, because the multiplier you need will be different for different velocities. Basically, you want to damp the components of the velocity that are not in the direction of gravity, right? Well, as soon as gravity has more than one non-zero component, things get messy. Your best bet is to not even try to compute the multiplier, just do the math to get the damped velocity.
Here is some sample code where I’ve done this, and this prints out the results for various directions of gravity and various velocities. You can see that the dampingV3 vector is sometimes unintuitive, because it can have components larger than the damping constant k
, in fact larger than 1! This is because the damping is actually changing the direction of the velocity.
Note that I’m also printing out what dampingV3
would need to be for each combination of gravity direction and sample velocity. Anywhere you see a component that’s an underscore “_”, that means it doesn’t matter, because it’s getting multiplied by 0, so any number would work there, e.g. 1.
local RNG = Random.new(1)
local directions = {
Vector3.new(1,0,0),
Vector3.new(-1,0,0),
Vector3.new(0,1,0),
Vector3.new(0,-1,0),
Vector3.new(0,0,1),
Vector3.new(0,0,-1),
Vector3.new(1,1,0).Unit,
Vector3.new(1,0,1).Unit,
Vector3.new(0,1,1).Unit,
Vector3.new(1,1,1).Unit,
}
local velocities = {
Vector3.xAxis,
Vector3.yAxis,
Vector3.zAxis,
-Vector3.xAxis,
-Vector3.yAxis,
-Vector3.zAxis,
RNG:NextUnitVector(),
RNG:NextUnitVector(),
RNG:NextUnitVector(),
}
local k = 0.75
for _, g in ipairs( directions ) do
for i, v in ipairs(velocities) do
local newV = k*v + (1-k)*(v:Dot(g))*g
local dampX = if v.X == 0 then "_" else newV.X / v.X
local dampY = if v.Y == 0 then "_" else newV.Y / v.Y
local dampZ = if v.Z == 0 then "_" else newV.Z / v.Z
print("g: ", "(".. tostring(g) ..")", "v:", "("..tostring(v)..")", "newV:", "("..tostring(newV)..")","dampingV3:","(",dampX..",", dampY..",", dampZ,")")
end
print("")
end
Just copy-paste that into a server script in ServerScriptService and let it run. The output is too long for me to paste it here. The takeaway is that for the arbitrary gravity directions and sample velocities, you get different damping vector components. Things are only simple when stuff’s all axis aligned.
So what is this code actually doing? Well one way to thing about it is that you want to scale your entire velocity by the damping constant k
, but they you want to undo this scaling only in the direction of gravity. This is accomplished in the code above by using a dot product to get the projection of the velocity onto the direction of gravity, so that that component can be added back after the whole velocity is scaled. Reduce it all by 75%, add back 25% only in the direction of gravity. How much the magnitude of the velocity changes depends on how aligned it is to the gravity direction, of course.