I'm also new to btKinematicCharacterController, and I'm not sure if my answers are all correct, just give some thoughts and experiences from my use here.
1, I really didn't notice the "character controller can't push dynamic objects correctly" thing until you mentioned. I test it in the demo, it seems to have some problems too. I do not really understand the dynamic calculation here yet, so I'll just wait someone else to explain it.
2, I never see the problem in CharacterDemo, and only met the same problem in my own app when I used "variable timestep" before. I could think that the only reason you still get problem when use fixed timestep simulation is that, you set that "fixed timestep" too high, like set max numbers of steps to 10, and in fact, this is equal to a "variable timestep" simulation in most cases.
I suppose you just use the code from CharacterDemo, that use "setWalkDirection" to update the pos of character every frame, without noticing that the the number of steps for simulation is fixed to 2 at maximum. See the code from CharacterDemo and also the comments I added
Code:
int maxSimSubSteps = m_idle ? 1 : 2; // NOTE: m_idle is always false here, maxSimSubSteps is fixed to 2
if (m_idle)
dt = 1.0/420.f;
...
m_character->setWalkDirection(walkDirection*walkSpeed);
// notice maxSimSubSteps here, we must limit the max nb of steps
int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps);
All I have to say is that, "setWalkDirection" is really misled here, you should read the comment of this method in btKinematicCharacterController.h, it should be called "setPositionIncrementPerSimulatorStep". Then what you see "the lower the framerate, the faster the character moves", should be just logical: when in a "variable timestep" simulation, lower the framerate, more the number of steps, so more the character moves.
In my app, I just get rid of this method. Instead, I use setVelocityForTimeInterval, as I also need the "variable timestep" simulation. Here is my code:
Code:
void MyCharacterController::UpdateMove( const btVector3& deltaPos, float deltaTime )
{
if (m_btCharacter)
{
btVector3 nextPos = deltaPos / deltaTime; // a little bit inefficient here, but necessary...
m_btCharacter->setVelocityForTimeInterval(nextPos, deltaTime);
}
}
and in this way, I could update the dynamic world in a normal way:
Code:
int numSimSteps = m_dynamicsWorld->stepSimulation(deltaTime, 10);
3, The CharacterDemo has a LOT OF memory leaks too, don't follow the example for memory management. The leak is not in btKinematicCharacterController though. See the code carefully for creation the character controller:
Code:
m_ghostObject = new btPairCachingGhostObject();
m_ghostObject->setWorldTransform(startTransform);
sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
btScalar characterHeight=1.75;
btScalar characterWidth =0.75;
btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
m_ghostObject->setCollisionShape (capsule);
m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
btScalar stepHeight = btScalar(0.35);
m_character = new btKinematicCharacterController (m_ghostObject,capsule,stepHeight);
so all is obvious, you have newed:
a btPairCachingGhostObject(m_ghostObject),
a btGhostPairCallback(unnamed, so need to add a variable here to track it),
a btCapsuleShape(m_ghostObject->getCollisionShape),
and finally btKinematicCharacterController(m_character).
And no, you could not just delete "m_character" here, because Bullet didn't help you to manage any newed memory, so you have to delete all of them by yourself
in the reverse order of creation/initialization.
btKinematicCharacterController works quite well here in my app, well, not perfect, as I also have some questions about it to ask. Just hope the above may give you some help.