How do I Disable and Enable Object Collision?

I’m trying to use two Edit Object >> Replace Mesh actuators, one with a normal mesh and other with a No Collision mesh. I have a property to define when it’s time to switch, but isn’t working.

Any help?

Either suspendPhysics or suspendDynamics, with ghost set to true(1).
You can read about object methods here.

For a quick test,

from bge.logic import getCurrentController;
own=getCurrentController().owner;

if(own["prop"]): own.suspendPhysics();

Indeed, the working method is suspendPhysics. The object that I was talking about is a door. The problem is that disabling physics still keeps the momentum or some kind of force, so when I disable it passing trough the player hitbox, after physics is restored and the player touches the door, it launches him away like a strong impact.

The best solution I have found is to disable the door hitbox permanently and add a flat collider block player passage when it closes.

If you want to add a bit more realism, instead of deactivating physics temporily, you could check to see which door direction the player is facing it (Front or Back). Then play an animation action based on which direction it is facing:

  • Facing door from front → Play door rotate backwards animation
  • Facing door from back → Play door rotate forward animation

That way physics will remain intact, but the door won’t be getting in the way of the player.
Note that you will need to setup extra logic, but the final result can be rather pleasing if you give it a chance.

Edit

Aye, that’s bullet physics alright.

You can force the player to be at a minimum distance before enabling physics, that ensures there won’t be any interjection or collision.

It is slightly more complex that the last example,

from bge.logic import getCurrentController;
from mathutils import Vector;
from random import choice;

own      = getCurrentController().owner;
player   = own.scene.objects["Player"];

if(own["prop"]):
    own.suspendPhysics();

cbox     = own.cullingBox.max;

vecTo    = player.worldPosition.copy() - own.worldPosition;
vecTo[2] = 0;

dist     = vecTo.length;
radius   = max(cbox[0], max(cbox[1], cbox[2]));

eps      = 1e-16;

if(dist<eps):
    player.applyForce(Vector([choice([-1,1]),choice([-1,1]), 0])*10);

elif(dist < radius*3):
    player.applyForce((vecTo).normalized()*6.5);
    
else:
    own.restorePhysics();
    own["prop"]=0;

So let’s unpack that a little.

  • radius is length of the larger side of the door’s bounding box.
  • vecTo is a direction pointing from door to player
  • dist is distance from door to player
  • eps is an ‘infinitely’ small value.
  • If distance is not greater than radius, push player away.

Radius is of course scaled up to compensate for Bullet’s ‘touchy’ syndrome, and the checking of distance under epsilon is only there to handle the fringe case where the objects are in exactly the same coordinate.

One problem with this is, of course, you need to make many checks per second. The smaller the force you apply, the more frequently you need to check. Notice how I’m scaling the forces by 10 and 6.5 – that is at one run per two frames, so thirty runs of the script per second.

If that’s an issue, you can just ‘teleport’ the player rather than apply force. This will look much more choppy however, but will require at most three or four runs to distance the player from the door.

To do that, you can just use the same script and replace the part where we apply force with an addition to the position vector:

if(dist<eps):
    player.worldPosition+=Vector([choice([-1,1]),choice([-1,1]), 0]);

elif(dist < radius*3):
    player.worldPosition+=(vecTo).normalized();

Do note that I ignore the specifics of your project, so you may have to tweak some of the scaling values to get a model like this to work properly.

zeroing worldLinearVelocity and world Angular velocity as well would help. irc, this applies while suspended, so zeroing right before enabling should do.

Yes, that might prevent the player from snapping into position if a collision triggers at the last frame. Doesn’t make much of a difference at minimum physics/logic steps, but I’m probably the only one running such toaster settings – trying can’t hurt.

Interesting. I assume that script is to neutralize this “launching effect” when player touches the door, indeed sounds pretty interesting. But the solution I’ve done so far is on a pretty comfortable spot, adding a flat collider prevents the player from glitching if they close the dor crashing him on the doorway edge.

image

The annoying part of giving door’s open and close condition to a flat hitbox is that the player will ignore door hitbox, but it solves a lot of problems and is not that bad while playing the game.

How do you want it to be?

Because you can simply make the door a no collision object, with open and close animation, etc. Then just use a place holder Plane in the door opening. So if you open the door you remove the plane, when closing you add the plane back in.

pros:

  • No door that will bump or move you or get’s you stuck
  • without to much hassle you can make the door shoot-trough

cons:

  • bit more to setup, but if you use multiple doors it could work perfectly fine and negates the additional work.

An other option, if door hits player simply stop animation, grab the frame where it stopped and reverse play the animation from that frame, so that the door hits player and directly goes to open state again (like the door is bouncing back kind of thing).

Many option to tackle this problem, simplest thing is to use capsule or cylinder box for the player.