I see this might be quite a basic thing, but I simply can get it to work as intended and am a bit confused with the physics and rigidbody stuff.
My player character can pick up boxes, that are then parented to the player body to move and rotate according to that object. The boxes are rigidbodies, which are set to kinematic when the player picks them up. However, as the player carries them around, they will just move through the walls of my level, which have only a box collider (not set to trigger) attached. I know that kinematic rigidbodies are not affected by physics but how can I prevent them from passing through level geometry? Do I have to add some additional component to the walls or change something on the boxes?
Many thanks in advance,
This is an odd problem, how are you moving the boxes? Manipulating the transform component, or using MovePosition (Unity - Scripting API: Rigidbody.MovePosition) i would suggest the 2nd one, I don’t think it does collision checks when you move it with the transform script.
@Cat_Ninja: Well, I’m not explicitly moving the boxes. They are moving according to the player as they are children of this object. I assume, however, that they are moved by internally by using their transform component (it’s just a guess though). I will definitely try your suggestion using Rigidbody.MovePosition, I didn’t know of that way to move stuff. Thanks alot!
They shouldn’t be going through your walls. If so are your walls planes? Rather make the walls cubes.
By the way, if something is kinematic, it still interacts with physics.
EDIT : Got this from the documentation…
“If you move the Transform of a non-Kinematic Rigidbody directly it may not collide correctly with other objects. Instead you should move a Rigidbody by applying forces and torque to it. You can also add Joints to rigidbodies to make the behavior more complex. For example, you could make a physical door or a crane with a swinging chain.”
In summary, perhaps it’s best to disable the rigidbody component on a box when you pick it up.
Then when it gets unparented, re-enable the rigidbody.
When dealing with kinematic rigidbodies, Unity assumes that if you moved it somewhere, then you know what you’re doing. If that somewhere is halfway inside a wall, then it assumes you know that too. It will try to move other non-kinematic rigidbodies around to account for that, but that’s all.
Ultimately, you’ve got to decide what should happen when you’re holding a crate and walk into a wall. Having the crate intersect the wall is no good, so what should happen instead? Should it stop the whole of your movement? Should the crate slide around in your hands? Should the crate get crushed?
Half-Life 2’s gravity gun, for example, would let you pick up objects, but if you bumped them into the environment they’d be pushed around (and potentially dropped if they got too far away from the tip of the gun). They’d return to the ‘center’ position when you moved back away from the obstacle. You could do something like this by not parenting the object to the player’s hands and making it kinematic, but instead using a physics joint of some kind to have the object be ‘pulled around’ by the player’s hand, while still having the physics system solve against collisions with walls etc.
First, yes the boxes have box colliders on them and the walls are cubes, that also have box colliders added.
I tried disabling (or destroying) the rigidbody of the boxes on pickup but it didn’t change anything. They would still go through the walls. Anyway, thanks for the answer.
What controller type are you using? if it is a character controller then the box is not counted as part of the collider of the character controller. You need to be using a physics character controller to make this work.
I’m actually using a character controller on my character. Never came across a physcis character controller. Is that that simply another component to add (I didn’t find such a one though) or how can I add one of these to my character?
OK. So effectively the box has become ‘part’ of the player.
How do you stop the player from walking into walls the rest of the time? I’m guessing you’re using CharacterController.(Simple)Move and it’s just taking care of collisions for you?
Sorry for bumping this but I am having the same issue. I can do something simple where I check my own collisions with a spherecast but I was wondering if there was a built in method that does this now and since it has been 4 years, maybe?
unity does have a manual layer based collision detection system in place so you could manually configure it so that your objects don’t collide. Go to Edit → Project Settings → Physics 2D (or Physics, depending on which Physics you’ve used). At the bottom of that settings panel, you’ll find a Layer Collision Matrix, which allows you to choose what can collide with another layer. since this is a layer based collision detection, you need to put all your game objects in layers. You can use existing layers, or better yet, create new layers for your game objects.
In this case, you could have put the boxes in one layer (and call it Box Layer) and the walls in another layer (call it Environment). You can now uncheck collision between Box and Environment and
When your Player picks up a box (I guess with OnTriggerEnter) send a message to that box (maybe same which you already use to be parented to Player) to set rigidbody.isKinematic=false; Then, as your Player leaves a box, just set rigidbody.isKinematic=true;
Use SweepTest in a script attached to box. It will act as a Raycast even if the box.transform.parent is set to Player and rigidbody.isKinematic is true or false;:
In that script, just check if something (Wall) will collide with box and stop movement, change direction or whatever your Player should do;
if (YourRigidBody.SweepTest(transform.forward, out hit, collisionCheckDistance))
// is this object going to collide with something in forward direction in the distance=collisionCheckDistance?
{
// ok we are in, did it collide whith a Wall?
if(hit.gameObject.tag=="Wall")
{
// stop Player, change direction, play sound, drop.... or... set isKinematic=false;
do events......
}
}
Hi. I put my walls to Environment layer and player to player layer. However, my player (isKinematic based controller) always goes through walls (isKinematic walls). I have unchecked everything, tried many variations and still player can go through walls. What am I doing wrong? Thanks
Why are the walls kinematic? Are they moving walls?
Do the walls have colliders?
Are you using MovePosition to move your character?
Edit: Actually, I think MovePosition will not do collision properly if everything is iskinematic. You can try it, though.
If your walls are not moving, remove the rigidbodies, keep the colliders, and make them static.
If you need both the walls and the player to be iskinematic for some reason, then I think you may have to implement your own collision handling. Rigidbody.SweepTest might help: