I have a sphere I can rotate with click and drag, but when activated, the cursor jumps to a random point on the sphere, which in turn jerks it to a completely different view. I want it to work smoothly in play, just like the regular blender click and drag does.

I added a video to YouTube. The first half is in object mode, where the cursor works the way it is supposed to. The second half is in "Play" and you can see the cursor jumps to the center of the board and the board jumps to a different position. I want it to be nice and smooth, like when in Object or Edit mode.


  • 1
    $\begingroup$ Are you talking about the system mouse cursor or a custom 3D mesh object? $\endgroup$ – Monster Feb 1 '17 at 6:28

This is because the mouse actuator 'snaps' the mouse cursor to the centre of the screen when you use it. So when you initially click on an object, the 'snap to the centre of the screen' causes the view to jump.

The solution is to use a custom script to do this sort of mouse panning:

import bge
import mathutils


def look(cont):
    if cont.sensors[0].positive:
        if HIDE_MOUSE:

        # Grab the location the mouse was clicked in:
        start_pos = cont.owner.get('PREV_POS', bge.logic.mouse.position)
        if HIDE_MOUSE:
            cont.owner['PREV_POS'] = start_pos

        # Calculate rotation difference to current position
        current_pos = bge.logic.mouse.position
        diff = mathutils.Vector(start_pos) - mathutils.Vector(current_pos)
        diff *= SENSITIVITY
        if Y_INVERT:
            diff.y *= -1
        # Rotate the objects
        cont.owner.applyRotation([0, diff[0], 0], True)
        cont.owner.children[0].applyRotation([0, diff[1], 0], True)
        current_rot = cont.owner.children[0].localOrientation.to_euler()
        current_rot.y = min(1.5, max(-1.5, current_rot.y))
        cont.owner.children[0].localOrientation = current_rot

        # Set the mouse position back to where it was
        if HIDE_MOUSE:
            bge.logic.mouse.position = start_pos
            cont.owner['PREV_POS'] = current_pos
        del cont.owner['PREV_POS']

However, this script requires a some setup of objects. It should be run from an empty parented to an empty parented to a camera.

It is much less time consuming for me to provide a blend file, so here you go:

Have a look at the set up, and try replicate it in your own system. Let me know if you have issues, and I can add more detail to this response.

  • $\begingroup$ Should I try to build this into the already existing script? Or should I make a new script altogether? (If so, I didn't know you could do that.) $\endgroup$ – quazipseudo Feb 3 '17 at 13:56
  • $\begingroup$ It should be a new script. You can have however many scripts you like $\endgroup$ – sdfgeoff Feb 4 '17 at 1:51
  • $\begingroup$ Does it matter where the empties are? How did you get empties that are big circles? Mine are little dots. $\endgroup$ – quazipseudo Feb 4 '17 at 17:37
  • $\begingroup$ I'm particularly confused about this: I've opened up the latest blend file and played around with it. It works fine. I then cut and pasted it into the ongoing blend file as a new module and set it up exactly the same, and nothing happens. It's counter intuitive that it would require it's own module. Which module runs first? last? or takes precedence over the other? When I first added the code blocks for using the arrow keys to rotate the board, you supplied the additional script to use click-drag and that was spliced into the original script. Why is that not the case with the new script? $\endgroup$ – quazipseudo Feb 5 '17 at 18:33
  • $\begingroup$ In the object data tab you can set how an empty is visualized. $\endgroup$ – sdfgeoff Feb 5 '17 at 21:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.