- Home /
How to make two colliders or rigidbodies stick together upon collision, as if there was a glue on their surfaces?
Friction does what I want for sliding, but I was wondering if there is something to prevent two colliders from getting separated as well. I want to make an "adhesive harpoon" that can release with a given keypress. Is there any way to get that effect while still keeping the objects separated?
This may work.
RigidBody body;
Transform collidedObject;
void OnCollisionEnter(Collision collision)
{
colliedObject = collison.transform;
if(!body)
{
if(collision.gameobject.GetComponent<RigidBody>())
{
body = collision.gameobject.GetComponent<RigidBody>();
}
}
if(body)
{
Destroy(body);
this.gameobject.transform.setparent(collision.gameobject.transform);
}
}
Void Update()
{
if(Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.space)
{
if(collidedObject)
{
collidedObject.parent = null;
collidedObject.AddComponent<RigidBody>();
collidedObject = null;
}
}
}
}
Answer by OutOfRam · Jul 27, 2018 at 04:19 PM
Hello, This could be achieved in a number of ways. The easiest would be to set one of the objects to be a child of the other, that way they will move together as though they are one object, but if you want to avoid parenting objects for whatever reason you could also try creating a fixed Joint (or spring joint if you want some elasticity) and the point of contact.
The following code snippet is more a guide, I wrote it in here and have not tested it so you will probably need to modify it
void OnCollisionEnter(Collision col)
{
// creates joint
FixedJoint joint = gameObject.AddComponent<FixedJoint>();
// sets joint position to point of contact
joint.anchor = col.contacts[0].point;
// conects the joint to the other object
joint.connectedBody = col.contacts[0].otherCollider.transform.GetComponentInParent<Rigidbody>();
// Stops objects from continuing to collide and creating more joints
joint.enableCollision = false;
}
I hope this helps
Oh my, this behaves exactly like what I was asking for, maybe even better (I was prepared to combine high-friction-materials to prevent sliding). The only problems I detected are:
1 - For reasons beyond my comprehension, it seems to only work on single-mesh/single-object rigidbodies I think. I tested it with my ship and a simple cube, worked flawlessly, but the rotating tunnel I had for testing various things (which is a rb made from 6 boxcolliders) didn't stick. I thought it could be the rotation or the burst of acceleration from the impact, but I threw the rotation script in the simple cube and still stuck to the ship.
2 - It didn't stick to non-rigidbody colliders either, I bumped the ship against a wall that I have there (just the collider and mesh) and it just bounced right back. $$anonymous$$inda not good, cause this was the original intended purpose (so the ship can park on a surface while the player uses its mechanical arms to interact with interactables, without having to coursecorrect all the time).
Fortunately in any cases, nothing seemed to break with my camera controller, movement, rotations, etc. No distortions or anything and that's really great! The only downside to how well it works is that it caused a shift in the center of mass (as expected IRL) that makes flying the ship really hard, since all the movement is based on relative accelerations, but hey, that's physics.
All that I need now is to find out how to break that joint, so the ship can let go. $$anonymous$$assive thanks for the help, though, that is really neat!
Hey,
A few questions: 1) Is the script attached to the root object of your ship 2) is the joint created on the multi-mesh objects, or is it failing to even create the joint 3) If yes, have you tried setting the torsion and break force to infinity as such:
joint.breakForce = $$anonymous$$athf.Infinity;
joint.breakTorque = $$anonymous$$athf.Infinity;
As for the non rigid body components the reason that does not work is because the joints rely on the unity physics engine and a rigid body component is essentially what allows an object to be effected be the physics engine. adding a ridgidBody and setting it to is$$anonymous$$inematic will allow the joint to be created, once created if you want the object to move with your ship, you will need to set is$$anonymous$$inematic = false. Otherwise the wall will remain stationary and the ship will either break the joint(if breakforce is not set to infinity) or it will stop moving.
To break the joint, merely use the Destroy() function
Destroy(transform.GetComponent<FixedJoint>());
and Finally if you want the center of mass to remain the same, you can set it manually as follows:
transform.GetComponent<RigidBody>().centerOf$$anonymous$$ass = Vector3(x,y,z)
I hope this helps
To be clear, with your non rigidBody objects, what I mean is in the editor add a rigidBody and set it to is$$anonymous$$inematic. a kinematic rigidBody allows the object to take part in physics interactions without the object itself being influenced. as such if you have a stationary wall that you want your ship to stick to, if you make the walls rigidbody kinematic it will stay put and not move within the scene, but your ship will still be able to create the joint and adhere to the wall. If you want the wall to then move with the ship, simply set is kinematic to false once the joint is created.
Sorry about the delay, was watching the lunar eclipse.
1 - Originally I intended on having an animated arm that would do the grabbing, so it would be a child object, but if I'm using it just for parking then I could use the ship's collider (which is a child object, since the root is actually an empty game object with the rigidbody). So I'd say all the tests I've performed were with the script in a child object. 2 - Sorry, I really don't know much about joints, I've seen a few videos on using them to make ropes and stuff, but I don't think I understood much. 3 - I'm trying that now. I've been testing it while typing this, and it looks like the script isn't working on the ship. I think I was understanding things wrong before, and probably left the script on the cubes I was testing with as well, ins$$anonymous$$d of just the ship. The test cubes, when scripted DO actually glue themselves to that one wall. I think it was just the script failing to work from inside the ship.
Honestly, the problem with the non-rigidbodies can be solved by making everything a rigidbody, I was just afraid of that being too heavy on the physics engine, since I'm quite new to this, I have no idea how much is too much, or what is better, really. I should probably do some research on that. From what I gather, I should go for rigidbodies anyway, kinematic or not, since I plan on having everything move and spin in all kinds of directions.
If I changed all of the necessary components/events to 2D, would the script work the same for 2D collisions?
Answer by Carterryan1990 · Jul 27, 2018 at 05:04 AM
I dont see why this wouldnt work.
RigidBody body;
Transform collidedObject;
void OnCollisionEnter(Collision collision)
{
colliedObject = collison.transform;
if(!body)
{
if(collision.gameobject.GetComponent<RigidBody>())
{
body = collision.gameobject.GetComponent<RigidBody>();
}
}
if(body)
body.isKinematic = true;
this.gameobject.transform.setparent(collision.gameobject.transform);
}
Void Update()
{
if(Input.GetKeyDown(KeyCode.space)
{
if(collidedObject)
{
collidedObject.parent = null;
if(body)
{
body.isKinematic = false;
body = null;
}
}
}
}
Sorry, I'm new to Unity and C# so I don't understand things very well, but your script seems to work in order to join objects together. However it kinda does it in reverse (as in the object that has the script becomes part of what it touches), which just obliterates my player no matter where in the hierarchy I put the script. The game is very physics-based, with free rotations, free movement, and such, when the player touches something, massive distortions take place and the controller becomes unstable (if it helps, I use AddRelativeForce + AddRelativeTorque for moving/turning and I did my camera control like this https://answers.unity.com/questions/1533526/best-way-to-rotate-child-and-parent-game-objects-i.html). If I place the script on the "targets", however (objects I'd like the player to "grab"), one problem I noticed is that if one of the "targets" that has been "grabbed" touches another, it grabs it too, which is not ideal, only the "grabbing part" or where the "adhesive" would be should be able to "grab" stuff, I also noticed some weird movements when multiple "targets" are present and touching eachother, as well as clipping.
This is a start, and it was pretty nice seeing something so close to what I wanted, but I was hoping more for a physics-based solution, since I knew using parenting would cause problems. $$anonymous$$aybe there should be two scripts? One for adhering to surfaces of non-rigidbody colliders and another for rigid bodies? But I don't know if that would even solve those problems or even make it easier to tackle. Thanks for the help though! I appreciate it!
You have multiple mistakes in the code syntax and also i don't know why, whether deliberately or because of an old syntax. but here how it should look correctly in 2019. Btw i`m not sure if the code works or not:
Rigidbody body;
Transform collidedObject;
void OnCollisionEnter(Collision collision)
{
collidedObject = collision.transform;
if (!body)
{
if (collision.gameObject.GetComponent<Rigidbody>())
{
body = collision.gameObject.GetComponent<Rigidbody>();
}
}
if (body)
body.is$$anonymous$$inematic = true;
this.gameObject.transform.SetParent(collision.gameObject.transform);
}
void Update()
{
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.F))
{
if (collidedObject)
{
collidedObject.parent = null;
if (body)
{
body.is$$anonymous$$inematic = false;
body = null;
}
}
}
}
}
Answer by jdgeci · Jul 27, 2018 at 04:58 AM
Have you considered adding a "Adhesive Point" to each. Like a component on the object. It Two plane, and each has a force of some huge magnitude pressing into the other. Because they're planes, theyll flatten against eachother. Friction then keeps it from sliding
I don't think I understood what you meant. Can you explain it a bit more? Is "Adhesive Point" something available in Unity like a bouncy physics material or do I have to make it myself? I also feel like I should point out that if one of the objects was being pulled away from the other, that is, perpendicular to the collision, I want them to be pulled together and not separated.