0
\$\begingroup\$

Edit: While I wasn't able to make the code work completely, I believe my question has been sufficiently answered.

I want to make two objects move, react to collisions and other stuff as if they were one.

For example, Objects A and B are entangled.

When Object C rams into Object A and starts moving with it, Object B should start moving with it. When Object B hits a wall, Object A should act like it also hit a wall.

I tried changing position/speed every frame, but this only works when done in one direction.

Now, I want all forces applied to any of the objects to also apply to the other objects entangled to it.

EDIT: The next step is making the thing work with one of the objects moving along a different axis(e.g. the opposite direction of the others) and at a different scale (e.g. speed is proportional to size). So fixed joints, while a working solution for the simplified version of the problem, don't work for me.

UPDATE: Here's the code so far, trying to figure out how to send the other object spinning in the same way as the first one, not sure how to set the position for the force(s?) applied

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class EEScript : MonoBehaviour
{
    public List<GameObject> activeObjects;

    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
    }

    private void OnCollisionStay(Collision collision)
    {
        OnCollisionEnter(collision);
    }

    private void OnCollisionEnter(Collision collision)
    {
        Rigidbody rigidbody = gameObject.GetComponent<Rigidbody>();
        foreach (GameObject obj in activeObjects)
        {
            Rigidbody rb = obj.GetComponent<Rigidbody>();
            if (rb is null || rb.gameObject==gameObject) continue;
            Debug.Log(collision.gameObject.name+"->"+obj.name);

            for (int i = 0; i < collision.contactCount; i++)
            {
                ContactPoint co = collision.GetContact(i);
                Vector3 relativePoint = co.point - rigidbody.centerOfMass;
                Vector3 normal = co.normal;
                Vector3 impulse = collision.impulse;
                if (Vector3.Dot(normal, impulse) < 0f) impulse *= -1;
                rb.AddForceAtPosition(impulse, relativePoint + rb.centerOfMass, ForceMode.Impulse);
            }
        }
    }
}
\$\endgroup\$
0
\$\begingroup\$

One thing you could do is, when one object experiences an impulse due to collision, apply it to the other too:

public Rigidbody[] entangledBodies;

void OnCollisionEnter(Collision collision) {
    // Unity sends the same impulse value to both participants in a collision,
    // even though one gets impulsed in the opposite direction. So which are we?
    Vector3 impulse = collision.impulse;
    if(Vector3.Dot(impulse, collision.GetContact(0).normal) < 0f)
        impulse *= -1f;

    // Transmit this impulse to all bodies entangled with this one.
    foreach(var body in entangledBodies)
        body.AddForce(impulse, ForceMode.Impulse);
}

If this is in 2D, you won't have a simple total impulse property available, but you can compute it yourself as shown in this answer.

To add torques, you'll need to iterate through the actual contact points in the collision manifold and add forces at the corresponding points of your entangled bodies.

\$\endgroup\$
  • \$\begingroup\$ The proper use of ForceMode.Impulse was the help I needed. \$\endgroup\$ – Dorijan Cirkveni Sep 12 at 13:54
  • \$\begingroup\$ However, using OnCollisionStay didn't work so I used OnCollisionEnter and multiplied the impulse vector by -1 with so far satisfactory results. Still need to test the stopping part of program \$\endgroup\$ – Dorijan Cirkveni Sep 12 at 13:56
  • \$\begingroup\$ Ah, you might need the impulse-flipping trick I use in the linked answer instead of a hard-coded -1 \$\endgroup\$ – DMGregory Sep 12 at 14:20
  • \$\begingroup\$ Works better now, still trying to fix for collisions where the first object is sent to a side rotating. How do I set position to apply force on when there are multiple contact points? \$\endgroup\$ – Dorijan Cirkveni Sep 12 at 14:42
0
\$\begingroup\$

Make one object a child of the other object or make both objects children of the same object. Add a rigidbody component to the parent object, but keep collider on both objects.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.