CollisionHandlerPusher and sliding against walls.


Like every newbie, I’m trying to prevent my avatar from going through walls.

I have something that kind of works but it’s weird, and I don’t know if it’s normal or not: The collisions are detected and I am always pushed back into a valid position. However, the whole part about sliding against the walls is messed up: I slide backward and end up stuck onto a convex corner for instance.

Is that expected with a CollisionHandlerPusher?

Here some details, maybe it can help:

My world is very simple, think “Wolfenstein 3D”: tile-based, no floor, no ceilings, walls are cubes (1x1x2 units in size, I think in meters).

I thought I could collide against the visible geometry since it was so simple (200 frames per second). My cube is exported from Blender with Yabee. I added the line " { Polyset descend keep }" (even though I don’t understand the “descend” part). Each wall in the maze is an instance of that cube.

I attached a CollisionNode to my avatar and gave it a CollisionSphere of radius 0.3 (or 30 cm). Since I changed the near-distance of my camera to 0.1, I never see through a wall.

This is how I set up the collisions:

        self.avatar = self.render.attachNewNode('avatar')
        self.avatar.setPos(Point3(0, 0, 1.5))
        avatar_col = self.avatar.attachNewNode(CollisionNode('avatar collision'))
        avatar_col.node().addSolid(CollisionSphere(0, 0, 0, .3))

        pusher = CollisionHandlerPusher()
        pusher.addCollider(avatar_col, self.avatar)

        traverser = CollisionTraverser('traverser')
        traverser.addCollider(avatar_col, pusher)
        self.cTrav = traverser

And this is how I move my avatar:

    def movePlayerTask(self, task):
        # self.keys is updated with events
        velocity = Vec3(self.keys['right'] - self.keys['left'],
                        self.keys['forward'] - self.keys['backward'],
        # Move relatively to the cam.
        quat = LRotationf(Vec3.up(), self.avatar.getH())
        velocity = quat.xform(velocity)
        # At a given speed.
        dt = globalClock.getDt()
        speed = 3.0
        # Teleport there.
        pos = self.avatar.getPos() + velocity * dt * speed
        return Task.cont

Am I doing something wrong?

Here’s a picture that illustrates what I think is going on.

The colliding object does actually slide against the wall. However, depending on where it hits the edge, it slides in a different direction: the direction of the closest vertex, as shown in the cases 1A and 1B.

I was expecting the behavior shown on 2A and 2B; how would you achieve this result?

After many tests and a lot of debugging, I figured out what my problem was:

  • If I read the collision solid from the egg file, or if I create a CollisionBox, then the pusher works perfectly and I slide gracefully against the surface.
  • If I create a bunch of CollisionPolygons myself, then the pusher is confused because each polygon is now a separate object: corners are a mess.

In short: 20 quads are not equivalent to one Polyset.

Which brings me to my next question:
[url]Procedural generation of collision polyset.]