getLinearVelocity always returns 0?

Hi! I have a fall damage script. This is it:

import bge

def main():
    
    cont = bge.logic.getCurrentController()
    own = cont.owner

    col = cont.sensors['GroundCOL']
    
    speed = own.getLinearVelocity()[2]
    
    print (speed)

    #own['Health'] = (5) only for testing if the script works

    if speed < -50 and col.positive:
             own['Health'] -= (2)
             
             
main()

Now, it removes health as needed, but not from falling. getLinearVelocity always returns 0, as I have checked in the console.

What could cause this?

What triggers the script? Meaning what sensors are connected to it. Just the collision sensor?

Nah, an always sensor, too.

Does the always sensor have true level triggering enabled so it constantly runs?

Yes. Yes, it does.

is the object a rigid body or dynamic?

Character.

yeah, that does not work

Character physics type… I don’t like and it’s not dynamic or rigid body, so none of that works

are you making a 2d or 3d game?

That seems kinda ridiculous…

3D game.

I see (this is my perspective on it) the character physics type to be in the same caste of objects as the mouse-look actuator. Quick-n-easy rigs for setting up rough prototypes with minimal viability. Not functional enough to hold their own on anything beyond that, but something you can plug in right away to have something to work with until you have something to replace it with. The mouselook actuator is great for what it’s good for: setting up mouselook in a couple seconds without having to touch a script. But that’s about it.

The problem with the character physics type is, unfortunately, that it’s straight-up broken. Fortunately though, there isn’t much that the character type does that dynamic/rigid body doesn’t also do. Step height is probably the only thing that wouldn’t be straight-forward.

Another thing: Just because your character is ‘moving’ doesn’t always mean that they have velocity. If you’re using the simple motion types (Loc/Rot), you are translating the object from point A to point B. If I jump into my teleporter and teleport myself 2mm to the left, how fast am I travelling? 0
If you want to be able to measure velocity on an object, you have to give it physics-based motion – Force, or setting the Velocity directly. And for physics-based motion to work, you need a physics-enabled object (dynamic/rigid-body).

step height = use a cylinder, with a cone compound parented on frame 0

this way, the actor goes up stairs as high as the top of the cone,


if keypress.positive:
    if own.localLinearVelocity.x<5:
         own.applyForce((50,0,0),1)



Workaround is to calculate velocity yourself.

import bge
import mathutils


def main(cont):
    own = cont.owner
    if not 'pos' in own:
        own['pos'] = own.worldPosition
        
    velocity = (own.worldPosition - own['pos']) * 60.0
    own['pos'] = mathutils.Vector(own.worldPosition)
    print (velocity)


if __name__ == '__main__':
    main(bge.logic.getCurrentController())

your going to need to use .copy() though right? pqfts


import bge
import mathutils


def main(cont):
    own = cont.owner
    if not 'pos' in own:
        own['pos'] = own.worldPosition
        
    velocity = (own.worldPosition - own['pos']) * 60.0
    own['pos'] = mathutils.Vector(own.worldPosition.copy())
    print (velocity)


if __name__ == '__main__':
    main(bge.logic.getCurrentController())

or it ‘solidifies’ a reference when you cast it as a vector?

Yep, I think it definitely needed .copy(), to be on the safe side :smiley:

And to read velocity from any object physics type, you could parent another rigid/dynamic objects to ones that don’t have it eg. I parented a cube(invisible/ghost rigid body) to my camera(no collision physics type), so that I could get those readings even when I don’t have a body/player

btw dynamic object have angular velocity too, just aren’t used to simulate the physics

No copy needed.

own['pos'] = mathutils.Vector(own.worldPosition)

… initializes a new vector object

I guess it would be shorter to type this, but it hurts my statically-trained mind

own['pos'] = own.worldPosition.copy()