RigIdBodyControl and CharacterControl

Hi. I have a problem when I want to make a NPC character to my game. So I decided to add 2 controls to my NPC model. RigIdBodyControl, cause NPC have to collide with my character and different things (terrain, scene). And also I added Character Control cause I wanna give my NPC ability to movement.

And there is a problem. If I add only RigId… collision is good, but NPC cannot move. But if I add only CharacterControl he can move, but collision with my hero is incorrect. And finally, if I add two controls to the node, my hero is flying somewhere and he stopped for a while (it looks like some force or forces are moving my hero when he is in the air) and I don’t know why.

Here is part of code:



[java]NPCcapsule = new CapsuleCollisionShape(1f,4.5f);

NPCcontrols = new CharacterControl(NPCcapsule, 0.05f);

NPCcontrols.setJumpSpeed(15f);

NPCcontrols.setFallSpeed(15f);

NPCcontrols.setGravity(40f);



.

.

.



node.addControl(NPCcontrols);

bulletAppState.getPhysicsSpace().add(NPCcontrols);



RigidBodyControl NPCcollision = new RigidBodyControl(NPCcapsule);

NPCcollision.setAngularFactor(0f);

node.addControl(NPCcollision);

bulletAppState.getPhysicsSpace().add(NPCcollision);[/java]



I red a topic about that and I tried solutions from there, but still I can’t fix it. Thanks in advance.

I think you can use only CharacterControl in this case…

Yes, You are right, thanks. Ok, I red few old topics and I know now that I have to add a GhostControl to both of my characters and create collision listener. But how to do that? Why CharacterControl can’t collide with different CharacterControl?

I think it is because it is very hard to make a control that both obeys the laws of physics (that the bullet engine is awesome at simulating) and at the same time breaks all the laws of physics by magically moving without using forces and not tripping over.

CharacterControl is a hack in bullet (not jME) to make it easier for simple cases only. Bullet is a physics simulation, not only a collision detection engine. But that is mostly my guesswork based on reading the bullet forums.

I uderstand.

Ok, I wrote my class in which i implemented PhysicsCollisionListener. And it works fine. My collision is detected. But I’m trying to stop my character when this collision will occured (of course I’m doing this in simpleUpdate method, but I have no idea how to do this correctly :D).

When collision is detected I set walkDirection of my hero on ZERO vector and it works, but how to return to moving when I for example go back?

I don’t know the best way but this is how I do it currently:

When the collision listener detects a collision I set a flag in my control to indicate I’m in collision, and then ignore the keyboard input from the user (and move the character back a bit from where he came from to get out of the collision). Then I count the time in update and when I have reached a “cooldown” threshold I decide that I’m out of collision and reset the flag. If I’m not out of collision the listener will set the flag again and so on.

Don’t know the best way to detect that there is no collision any longer, I simulate a sort of NoCollisionListener :slight_smile:

1 Like

Thanks for reply. Ok, I understand your solution, but I don’t know how to correctly move my characterControls in right place after collision. I used something like this, but of course it doesn’t work correctly:

Vector3f location = controls.getPhysicsLocation();

controls.setPhysicsLocation(new Vector3f(location.x,location.y,location.z - 0.05f));

I know why it doesn’t work like I want. This translation moves my controls capsule into specific place.But I have to know from which direction my hero comes. Any idea how to implement this?

I have implemented an idea like this

use charactercontrol to move and ghost to detect collision like in other posts

  • PhysicsRayTestResult (you can find a test case in source code of jme3)

    +movable boolean

    +up, down left right boolean



    so when you press a key, I will shoot a ray in the direction your character will move, to see if there will be any obstacle in the way

    then check ghostcontrol if there is any collision, if yes set movable = false, else set movable = true.

    and then somewhere in your code or in simpleupdate

    [java]

    if (cuTank.isLb()) { //left arrow pressed ->left boolean = true

    cuTank.getPhysicsControl().setViewDirection(new Vector3f(-1,0,0));

    if (movable==true) {

    cuTank.getPhysicsControl().setWalkDirection(new Vector3f(-cuTank.getMovementSpeed(), 0, 0));

    }

    else{

    cuTank.getPhysicsControl().setWalkDirection(new Vector3f(0, 0, 0));

    }

    }//left

    [/java]



    this way of pre detection is better than post detection imho.

    long ago I made 4 hitbox around a character to check where did my character comes from and

    so.

    ps: character + rigid wont work together, there will be different strange things happen. at least by the time i tested long ago
2 Likes

UP: Thanks for your solution but I made it like jmaasing and it works (not perfectly but for me is sufficient). Here is my code, maybe will be helpful for somebody with this problem. Thanks both of you :slight_smile:

CollisionControl.java



[java]public class CollisionControl extends GhostControl implements PhysicsCollisionListener

{



//declarations

private boolean block = false;



public CollisionControl(BulletAppState bulletAppState, CapsuleCollisionShape capsule)

{

super(capsule);

bulletAppState.getPhysicsSpace().addCollisionListener(this);

}



@Override

public void collision(PhysicsCollisionEvent event)

{

if(event.getNodeB().getName().equals(“NPCnode”))

block = true;

}





public boolean getBlock()

{

return block;

}





public void disableCollision()

{

block = false;

}





}[/java]



And in simpleUpdate method:

[java]//to compute collision with different characters

if(collision.getBlock() == true)

{



//characterControls go back a little

if(collisionTime == 0)

{

int place;

place = iteration - 30;

if(place < 0)

place = 100 + place;





controls.setPhysicsLocation(locations[place]);

}



block_keys = true;

collisionTime++;



//when disable collision?

if(collisionTime > 1)

{

collision.disableCollision();

collisionTime = 0;

}

}



//



else

{



//


//remembering last 100 locations of character (needed to collision with different characters)

locations[iteration] = new Vector3f(controls.getPhysicsLocation());

iteration++;



if(iteration == 100)

iteration = 0;

(…)

[/java]

collision is a CollisionControl object.



locations
is a table into I’m putting last hero positions (it can be of course smaller than 100).



And now I know that RigIdBodyControl and CharacterControl can’t work together :slight_smile:

I was thinking about pre-detection also but started with this approach and haven’t bothered trying to refine it. I will probably try pre-detection sometime in the future, it is a little more complicated when the collision shape is a box or mesh and you must take rotation into account also, but still might be a good idea.



I don’t track the previous locations, I use the collision normal like this

[java]event.getNormalWorldOnB()[/java]

If the character is not NodeA in the collision event I will negate the normal. Then I move a bit in the direction of the normal and hope that brings me out of collision. It is far from perfect but it works ok in my case (much open space and few obstacles).

Oh, so it is for sure easier solution than mine. I didn’t know that something like event.getNormalWorldOnB() exist :smiley:

Anyway, would be really easier and better if collision between two characters be part of the engine. I know that probably is really hard to do it, but almost all games have NPC and monsters and this type of collision is necessary. Maybe in future… :slight_smile:

this topic was very useful for me.
I think this topic should be kept for newbie.
(at least, until CharacterControl will improve…)