0 votes

I have a box floating in space, the player moves the box around to catch falling objects across the x and z axes.
The box should not react to any of the falling objects.

I feel like I've tried everything but I cannot get this to work.
If I use a RigidBody with mode=Kinematic, then I cannot get it to move at all.
If I use a KinematicBody with MoveAndSlide or MoveAndCollide in _PhysicsProcess, then the box gets pushed about by the moving objects. If it catches one of the falling objects, then it is continuously pushed downwards by the object's gravity.

SetLinearVelocity does nothing as far as I can tell, and it struck me as odd that it isn't even an available function in the KinematicBody node type.

asked May 13 in Engine by hedgehog90 (14 points)

1 Answer

+1 vote

You're using bodies that are designed specifically to provide collision, and then expecting them not to collide.

If you don't want any collisions, make your box an Area. Use its body_entered signal to catch the falling objects.

Linear velocity is a physics concept, and kinematic bodies specifically don't participate in physics - that's what rigid bodies are for. Kinematic bodies are for collision detection, but you must move them and calculate collision response yourself.

I highly recommend reading this document to understand how each CollisionObject works and how/why you should choose one over another:
http://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html

answered May 13 by kidscancode (5,626 points)

Sorry, my definition of box is probably not the one you had in mind - I meant like a cardboard box, 4 sides and a bottom. IOW a vessel to catch and contain other collision objects.

Blockquote
Kinematic bodies are for collision detection, but you must move them and calculate collision response yourself.

How do I do that then?
I want a rigid body that collides with objects, but is not influenced by them or gravity, and can be moved around in the context of the physics environment (ie, not setting the spatial's transform directly, but using velocity to define the object's position).

In other words, any collision forces to the box must be ignored, it should not be influenced by them even slightly, but it must also allowing movement of the box from the player across the x and z axis.

I've tried using _IntegrateForces on a plain RigidBody to alter the state, which allows the kind of rigid movement I'm looking for, but I still can't find a way of effectively nullify the forces of the falling objects on the box.

Another issue ofcourse is that MoveAndSlide and MoverAndCollide stop dead on encountering a movable rigidbody.
I'm sure this is not an issue in other physics engines and this behaviour seems totally unintuitive.
From experience, I've used kinetic bodies in Box2D and Unity for what are essentially animated bodies, moving on a fixed path (like a moving 3d platform) and they work as assumed - the kinematic body if it hits an object, moves the object and doesn't slow down itself.
I just can't recreate this behaviour though.

I've come across a similar issue on github, people are suggesting there should be a moveandpush function: https://github.com/godotengine/godot/issues/7130
How can I implement this myself?

I see, yes, I didn't understand what your "box" object was doing.

What I mean by "calculate yourself" is that a KinematicBody doesn't react to a collision, it just stops, as you've seen. If you want a bounce, push, or other response, that's where you have to start writing code.

When the body collides, you get a KinematicCollision object, containing information about the collision: colliding body, normal, contact point, etc. You can use this information to apply a velocity, bounce off, or some other response.

On the other hand, if you're using RigidBody, there's axis_lock_linear_y which should let you lock the box to a plane, although I can't say I've tested that very extensively.

You can use this information to apply a velocity

How?

SetLinearVelocity is not available to a KinematicBody, and MoveAndCollide is not available to a RigidBody.
Even with the information from the KinematicCollision, I can't find any way to alter the linear velocity of the kinematic body if an object is colliding with it.

Typically when using a KinematicBody you use a velocity variable of some kind. Again, with kinematics, you have to do the motion stuff yourself. You could write your own "impulse" function on the body and call it when colliding.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.