Player goes straight through walls despite CollisionPusher

Hi,

I am currently testing simple collisions from my moving car (CollisionBox) and walls/obstacles (CollisionBox), using CollisionPusher.

So far, I have got the collisions working in the sense that the walls do push back against the player, and (kind of) stop it from moving, and allow me to slide along the wall. However, if I keep attempting to move forward, the player tunnels straight through the wall.

I have tried using pusher.setHorizontal(True) to prevent it from scaling the wall but this only prevented the object from moving over the wall, not straight through it.

How to I make sure the car does not magically end up on the other side of the wall? What am I doing wrong?

Key part of code:

# Model initialised and rendered to render as parent
colNode = model.attachNewNode(CollisionNode(nodeName))

# Wall Handling
# Initialise pusher collision handling
pusher = CollisionHandlerPusher()

pusher.addCollider(colNode, self.model, base.drive.node())
# pusher.addCollider(colNode, base.camera , base.drive.node())

pusher.addInPattern('%fn-in-%in')
pusher.addOutPattern('%fn-out-%in')

# Problem is the racecar will attempt to scale the wall
# Unfortunately still does not fix it
# TODO: Try http://www.panda3d.org/manual/?title=Rapidly-Moving_Objects
pusher.setHorizontal(True)

base.cTrav.addCollider(colNode, pusher)

Thank you!

Hmm… Are you updating your car’s velocity on contact with the wall?

For one thing, it occurs to me that if your car’s velocity becomes too high, it might eventually more or less “teleport” to the other side by virtue of moving so fast that a single position-update moves it entirely to the other side of the wall.

I do note that you have the “rapidly-moving objects” page bookmarked there; the approach given there may well help.

However, the main thought in reducing the vehicle’s speed is that when one drives against a wall, one would expect the vehicle’s speed to decrease–and that decreased speed may help to keep the physics simulation stable.

[edit] Another thought: how are you updating your vehicle’s speed and position? Are you doing it in a task?

Hi thanks for the reply!

I think you are right that the velocity becomes high. I note that the position of my player continues to get updated when my arrow keys which move the player are pressed, until it just teleports to the other side. Why is the pusher not negating this effect though?

Also, yes, I am using a task to update the car’s position.

To summarise, I am using a friction/acceleration based movement system. When the user presses up, the acceleration increases. When the user presses down, the acceleration decreases. An infinitely running task starts a movement function which updates the velocity and acceleration, and then positions, accordingly.

Strangely, I’m already setting the speed and accelerations to 0, in both the in and again events, but the car still teleports and tells me that the car’s position changes even though it is colliding with the wall.

What workaround do you suggest? And why does the Pusher event not “push” enough to counteract my movement. I have made my collision box insanely large, and it still moves through the box (this time without teleporting; it now moves smoothly through it).

If I’m not much mistaken, the pusher doesn’t exert physical forces–all that it does is to attempt to prevent objects from intersecting. In short, it updates the position of the “from” object such that it’s no longer intersecting with the “into” object–and that’s it.

The expectation, I think, is that you handle velocity of the objects in question, including how the velocity should change in response to a collision.

Indeed, I imagine that your vehicle’s velocity is stored in a variable of your own; a Vec3 somewhere, perhaps. If so, then Panda’s collision system presumably doesn’t know about that variable, and thus isn’t in a position to alter it.

Okay, fair enough–that should be fine, I think.

Hmm… That is odd. Could I see the code for your “in”- and “again”- events, as well as the code in which you update your vehicle’s position and speed (the latter including the handling of friction and player input), please?

Thank you for your help!

Yes it is. I realise that this might actually be a problem, because I am updating my own position via the x, y, z variables I am storing in my class, but these positions are not updated with the model’s position.

This might be the reason why I am visually seeing the model not moving but my internal (x,y,z) positions changing. I will try obtaining the positions from the model and increasing my velocity from the model’s x,y,z positions instead of my internal ones.

Ah, yes–I think that may well be the source of your problem. What I think that I’ve usually done is pretty much what you suggest as a fix: the model (or, oftentimes, a “handle” NodePath above the model) holds the object’s position. I store the object’s velocity in a simple Vec3, and apply it to the relevant NodePath to update the position. If I want to access the model’s position, I retrieve it from the NodePath.

It’s seemed fairly reliable when I’ve used it, I believe!

1 Like

Yep! I fixed it by using the positions retrieved from the NodePath instead of from my own object!

Thank you for your help!

1 Like

Ah, excellent! I’m glad that you got it working, and the help is my pleasure. :slight_smile:

1 Like

I am also using CollisionPusher and my “from” object also goes through the “into” objects. The way I update my “from” object is:
self.ball.setY(self.ball, self.vel)
The object only goes forward when the user tells it to.

I don’t understand

Can someone explain how to achieve this?

Thanks in advance!

Based on the code that you posted there, that might not be the solution in your case.

In the case that you quoted, if I’m not much mistaken: The poster was storing their object’s position in a separate variable, updating that, and then setting the object’s model to be located in that new position. This meant that while the CollisionHandlerPusher was updating the model’s position as appropriate, it wasn’t affecting the variable in which they stored their position, and so that position eventually moved past the obstacle and their model thus did so too.

As to your case: If I may ask, are you altering your ball’s velocity when it impacts an obstacle? And are there any limits on how high that velocity can be?

(Also, I note that you’re not applying the time since the last frame to your velocity. Are you using a fixed frame-time?)

My ball’s velocity is constant, it does not change at any time.

I am using a CollisionPolygon as my “into” object, but it is 2D. Can this be the problem?

Ah, it could be: I do think that CollisionPolygons are less reliable than other forms of collision solid.

That said, it may be a problem that your ball’s velocity never changes–especially when dealing with an infinitely-thin CollisionPolygon. Over successive frames the ball may move closer and closer to the obstacle, until it’s close enough that the collision system has trouble with it. But I may be mistaken in that.

You might be able to improve matters a bit by reducing your velocity a little, perhaps, reducing the probability of the ball “slipping through”.

However, if feasible, I recommend switching to a different collision solid.

If that’s not feasible, then you might try activating Panda’s support for rapidly-moving objects, as described here.

The situation got even weirder. The CollisionPusher detects walls when the ball is moving in the negative direction (Left, Backwards), but not in the positive direction (Right, Forwards).

I tried enabling the support for rapidly-moving objects, it sadly didn’t help.

I switched Collision Handlers just to CollisionHandlerEvent, which I am fine with because I can still do what I want with a few extra lines of code, and it now works.

I appreciate your help and I will consider your advice when I do new projects in the future!

I’m glad that you got it working! :smiley: And I’m glad if I’ve been of service, for this project of subsequent ones. :slight_smile:

As to the pusher only working when you move in a specific direction, I wonder whether the wall’s normals weren’t facing only in one direction, and thus only pushing the ball when it approached from that direction, or only pushing it in that direction (I’m not sure of quite how it works in that respect).

CollisionHandlerEvent, however, likely just detects the overlap, and so responds regardless of direction.