BulletCharacterController Not Working

Hello!, I have encountered an error in the character controller. I am clicking w, but it is not moving forward.

from direct.showbase.ShowBase import ShowBase
from direct.showbase.InputStateGlobal import *
from direct.gui.DirectLabel import DirectLabel
from direct.gui.DirectButton import DirectButton
from panda3d.core import *
from panda3d.bullet import *

loadPrcFile('config/Config.prc')

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.menu()

    def menu(self):
        self.label = DirectLabel(text='Fight 4 Life', pos=(400, 0, -250), scale=50,  parent=self.pixel2d)
        self.button = DirectButton(text='Play', pos=(400, 0, -350), scale=50, parent=self.pixel2d, command=self.game)

    def game(self):
        self.label.hide()
        self.button.hide()
        
        self.disableMouse()
        
        inputState.watchWithModifiers('w', 'forward')

        self.world = BulletWorld()
        self.world.setGravity(0, 0, -9.81)

        self.groundNode = BulletRigidBodyNode('Ground')
        self.groundShape = BulletPlaneShape(Vec3(0, 0, 1), 1)
        self.groundNode.addShape(self.groundShape)
        self.world.attachRigidBody(self.groundNode)
        self.groundNP = self.render.attachNewNode(self.groundNode)
        self.groundNP.setPos(0, 0, -2)
        self.groundModel = self.loader.loadModel('models/ground.bam')
        self.groundModel.setScale(100, 100, 100)
        self.groundModel.reparentTo(self.groundNP)

        
        self.boxShape = BulletBoxShape(Vec3(5, 5, 5))
        self.boxNode = BulletCharacterControllerNode(self.boxShape, 1.0, 'Box')
        self.world.attachCharacter(self.boxNode)
        self.boxNP = self.render.attachNewNode(self.boxNode)
        self.boxNP.setPos(0, 0, 2)
        self.boxModel = self.loader.loadModel('models/model.bam')
        self.boxModel.hide()
        self.boxModel.reparentTo(self.boxNP)
        
        self.taskMgr.add(self.update, "Updates the scene")
        
    """def setKey(self, key, value):
        self.keyMap[key] = value"""
    
    def update(self, task):
        dt = globalClock.getDt()

        self.world.doPhysics(dt)

        speed = Vec3(0, 0, 0)
        omega = 0.0

        if inputState.isSet('forward'): speed.setY( 3.0)
        """if inputState.isSet('reverse'): speed.setY(-3.0)
        if inputState.isSet('left'):    speed.setX(-3.0)
        if inputState.isSet('right'):   speed.setX( 3.0)
        if inputState.isSet('turnLeft'):  omega =  120.0
        if inputState.isSet('turnRight'): omega = -120.0"""

        self.boxNode.setAngularMovement(omega)
        self.boxNode.setLinearMovement(speed, True)

        self.camera.setPos(self.boxNP.getPos())
        
        return task.cont

game = Game()
game.run()

You have to call self.world.doPhysics() periodically (in a task) to let the physics engine do its calculation and update all the physical objects.

I have called it. See the update task.

I see, it’s preferable to update the physics after you have handled your inputs.

Also,

        inputState.watchWithModifiers('w', 'forward')

is wrong, it must be

        inputState.watchWithModifiers('forward', 'w')

Nope, still not working

With the modification above, the speed and the position of boxNode (and so camera) are updated each frame, so that part of the code works.
Probably you have other errors in your code not related to BulletCharacterController.

If I may ask, why are you building core definitions the way that you are? Are you making sure to actually call them somewhere in the file? Why not just put those declarations in a single main body? Also, be careful about calling what should be one-time definitions with each frame update.

I am doing the definitions as I want to apply physics to the camera, so I thought I would apply them to the box and then set the camera pos to the box every frame.
I don’t know if this is the best method but I am using it.

Hi! Whatever I do doesn’t seem to work so here is the code I have as of now:

from direct.showbase.ShowBase import ShowBase
from direct.showbase.InputStateGlobal import *
from direct.gui.DirectLabel import DirectLabel
from direct.gui.DirectButton import DirectButton
from panda3d.core import *
from panda3d.bullet import *

loadPrcFile('config/Config.prc')

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.menu()

    def menu(self):
        self.label = DirectLabel(text='Fight 4 Life', pos=(400, 0, -250), scale=50,  parent=self.pixel2d)
        self.button = DirectButton(text='Play', pos=(400, 0, -350), scale=50, parent=self.pixel2d, command=self.game)

    def game(self):
        self.label.hide()
        self.button.hide()
        
        self.disableMouse()
        
        inputState.watchWithModifiers('forward', 'w')

        self.world = BulletWorld()
        self.world.setGravity(0, 0, -9.81)

        self.groundNode = BulletRigidBodyNode('Ground')
        self.groundShape = BulletPlaneShape(Vec3(0, 0, 1), 1)
        self.groundNode.addShape(self.groundShape)
        self.world.attachRigidBody(self.groundNode)
        self.groundNP = self.render.attachNewNode(self.groundNode)
        self.groundNP.setPos(0, 0, -2)
        self.groundModel = self.loader.loadModel('models/ground.bam')
        self.groundModel.setScale(100, 100, 100)
        self.groundModel.reparentTo(self.groundNP)

        
        self.boxShape = BulletBoxShape(Vec3(5, 5, 5))
        self.boxNode = BulletCharacterControllerNode(self.boxShape, 1.0, 'Box')
        self.world.attachCharacter(self.boxNode)
        self.boxNP = self.render.attachNewNode(self.boxNode)
        self.boxNP.setPos(0, 0, 2)
        self.boxModel = self.loader.loadModel('models/model.bam')
        self.boxModel.hide()
        self.boxModel.reparentTo(self.boxNP)
        
        self.taskMgr.add(self.update, "Updates the scene")
        
    def update(self, task):
        dt = globalClock.getDt()

        speed = Vec3(0, 0, 0)
        omega = 0.0

        if inputState.isSet('forward'): speed.setY( 3.0)
        """if inputState.isSet('reverse'): speed.setY(-3.0)
        if inputState.isSet('left'):    speed.setX(-3.0)
        if inputState.isSet('right'):   speed.setX( 3.0)
        if inputState.isSet('turnLeft'):  omega =  120.0
        if inputState.isSet('turnRight'): omega = -120.0"""

        self.boxNode.setAngularMovement(omega)
        self.boxNode.setLinearMovement(speed, True)

        self.camera.setPos(self.boxNP.getPos())

        self.world.doPhysics(dt)
        
        return task.cont

game = Game()
game.run()

Of course I am. I just started developing the game. I will definitely need them later on.

Based on some quick testing, it looks to me like the code is working, but your speed is quite low and your ground is quite big, so it appears that you’re not moving.

So I should just increase the speed or decrease the ground scale?

And also, even though I am positioning the model to a high z, why is the camera still too low down?

That’s perhaps something for you to experiment with, I think. Both changes may have effects on other aspects of your gameplay.

I would imagine that it’s because, in your “update” method, you’re setting the camera’s position to be that of “self.boxNP”–that will be overriding any previous position-setting.