Home > Software design >  How to evenly distribute resistance on a 3D Vector?
How to evenly distribute resistance on a 3D Vector?

Time:01-05

I am making a game in Godot where different places will have different resistance against movement, and I use this code:`

direction.x = move_toward(direction.x, 0, resistance * delta)
direction.z = move_toward(direction.z, 0, resistance * delta)`

So if my velocity is for say Vector3(14.14,0,0), I'm moving along the X axis by 14.14, but the resistance is 3, my speed will be 11.14 then. But if my velocity is Vector3(10,0,10), I'm moving along the X axis by 10 and Z by 10 and ill be moving at a speed of 14.14, but the resistance will make the vector this: Vector3(7,0,7) and instead of my speed being 11.14 its 9.89. How would I fix this?

CodePudding user response:

It appears you want to keep the same direction but change the length of the vector.

The shorthand for that is limit_length. So, to make the length shorter by the amount you want, you can do this:

var length := vector.length() - resistance * delta
vector = vector.limit_length(length)

Well, except that when the length we input is negative it gives you a vector in the opposite direction, which I suppose you don't want. We can fix that with move_toward:

var length := move_toward(vector.length(), 0.0, resistance * delta)
vector = vector.limit_length(length)

Or, since we know the value will be decreasing (the length of a vector is never negative), we can do this:

var length := max(vector.length() - resistance * delta, 0.0)
vector = vector.limit_length(length)

Note that limit_length was added in Godot 3.5.

In case you need it, this:

vector = vector.limit_length(length)

Is equivalent to this:

var old_length := vector.length()
if old_length > 0.0 and old_length > length:
    vector = vector * length / old_length

Put that toghether:

var length := max(vector.length() - resistance * delta, 0.0)
var old_length := vector.length()
if old_length > 0.0 and old_length > length:
    vector = vector * length / old_length

We can simplify a bit:

var old_length := vector.length()
if old_length > 0.0:
    var length := max(old_length - resistance * delta, 0.0)
    vector = vector * length / old_length

I'm not suggesting this is better (I expect it to be worse performance). Instead I want to demystify limit_length and move_toward. Plus this is what you would do before Godot 3.5.

  • Related