Python Sets Position with One Frame Lag

Let’s pretend I want to attach a dart to a wall without parenting it to the wall, such that when the wall moves, tilts, or rotates, the dart appears to stay fixed to the same exact spot on that wall. Furthermore, let’s assume my python scripts are handling the math to accomplish this, no problems there.

The real problem essentially is, the position that they calculate for the dart is correct for the previous frame. So if I have a wall moving 60km/h out in space, the dart moves 60km/h accordingly (because python scripts calculate and set its position relative to the wall) but it lags behind by one frame.

Presumably, this is because the python logic gets executed before objects in the world (with linear and/or angular velocity) are moved. Does anyone know how to mitigate this problem?

I have attached a simple .blend file demonstrating this behavior. I turned the framerate way down to make the problem easier to see. Ideally, the red pyramid just barely touches the cube’s corner, but when you press P and start the game, there is a gap between the two as the cube moves. Increasing cube_speed (from the script) increases the gap.

Attachments

child_point_test.blend (437 KB)

Not opened the blender but, are you making sure to move first the wall and then the dart? The order matters.

you can use

own.worldPosition = object.worldPosition+(object.worldOrientaition * vector(local offset))
own.applyMovment seems to not update as fast

if this is not working, you can use the LinV / frame step or something like that to move ‘in sync’

else, if your moving the wall with apply movement, just have the wall apply the same movement to the dart?

lastly are you using the bump order hack?

For some reason setting an object’s worldTransform attribute takes 1 frame to be applied. You can get around this by setting the worldPosition, worldOrientation, and worldScale attributes separately as they all take affect instantly.

Hi, you should check if you can avoid to mix logic and python to see if it can solve your problem (and use worldPosition and worldOrientation instead of applyMovement and applyRotation). I made a patch to solve the issues but I don’t know if it can generate other bugs: https://developer.blender.org/T43325 http://www.pasteall.org/62288/diff (update scenegraph when calling applyMovement && applyRotation and process actuators (update gameobject positions) before controllers (where you have your python script). (I tested your file with my fix and it worked)

EDIT: Thanks Mobious for worldTransform… I didn’t know that it has the same problem… Ah you can workaround without delete motion actuator?

What I do per moment is use scene.pre_draw, it is “A list of callables to be run before the render step” (what the api says). So every function register here will run before the render.

This is an example:

from bge import logic

#This function will be executed before the render step
def adjustPosition():
    #Put your math here
    logic.objectB.worldPosition = logic.objectA.worldPosition
    
def game(controller):
    owner = controller.owner
    scene = owner.scene
    
    #If the module logic doesn't have the attribute "objectA", initialize the data
    if not hasattr(logic, "objectA"):
        #Save the objects in a place accessible everywhere, you can also save the scene and get the objects inside the function
        logic.objectA = scene.objects["player"]
        logic.objectB = scene.objects["object"]
        
        #Append the function to scene.pre_draw
        scene.pre_draw.append(adjustPosition)

What the script do is register a function that adjust the position of a object to another one, it’s register in the first frame. In this way you avoid the 1 frame delay. You can’t use logic.getCurrentController() or logic.getCurrentScene() inside the function, that’s why I save the objects in bge.logic.

Thank you for the responses. I did a little more experimenting, but unfortunately I haven’t been able to fix it yet.

To clarify, in my project (not seen in the example), the real “wall” in question has linear and angular velocity which are set indirectly through object.applyForce() (whether applyForce() is called before logic, after logic, or even not at all has no effect on the problem). The movement is purely pythonic, but even something as simple as thisObject.worldPosition = thatMovingObject.worldPosition lags by a frame (see the new example attached).

Using LinV / frame step is a suitable hack that I’d thought of, but it only works for dynamic physics type objects (realistically speaking, most walls will be “static” and may move only manually. I want my project to work for both types). I may use it anyway; do you know how to get the frame step from the bge module? (I’d rather not use a magic number if I don’t have to).

I’m not sure what the bump order hack is, do you have a link to an explanation?

Making this change unfortunately seemed to have no effect on the example. Additionally, in my project, I am already setting worldPosition separately anyway. I will keep this in mind, however, as it is very good to know.

I’m not sure what you mean, should I avoid using motion actuators to move certain objects and python controllers to move others? I know movement can be implemented purely in python, but for simple objects I’m not sure what the tradeoffs are. In any case, as stated above, my real project involves an object moving via applyForce() and has no motion actuators attached.

This is a helpful tool. I hope I don’t have to resort to it since it seems like it should be used more as an exception than a convention, but it might be the best way.

I have attached another (simpler) blend file that demonstrates the same broken behavior with a dynamic physics object. Use left and right arrow keys to move the cube, and notice that the cone above it (whose position is set via cone.worldPosition = cube.worldPosition) lags behind.

It could be that there’s no clean way to hack my way out of this problem, but I’m very interested to learn about the nuances of the game engine to avoid any pitfalls. Both examples that I’ve posted are two uses cases in my project, anything that would fix both would be valuable.

Attachments

python_position_lag.blend (417 KB)

there is a little box which reads ‘mark this in controller to bump order’

this makes a operation happen before others,

so, script 1 = moves wall (marked first) script 2 moves attached object?

I would store the localized hitPoint of the intial dart in the dart, and the object it’s ‘stuck’ to,

local = target.worldPosition-own.worldPosition
local = own.worldOrientation.inverted()*local

or something like that :smiley:

edit: never mind! you are right! I tried my method (setting a localized position and setting a localized rotation) it is like slow parent 1 frame!

so I will need to get used to using the new version when it hatches!

did a thrurough investigation and here it is :smiley:

my method is in fact 1 frame behind : D

Attachments

BugTest.blend (513 KB)