Search Unity

Question Looking for a better way to snap two objects together programmatically

Discussion in 'Physics' started by TheBulletKin, Dec 7, 2023.

  1. TheBulletKin

    TheBulletKin

    Joined:
    Jan 5, 2022
    Posts:
    12
    So I'm essentially aiming to build a system somewhat like Tears of the kingdom, whereby you move objects around, and 'glue' them together when they intersect another object, but I've come to realise that my currentl implementation is going to be rather restrictive as it is now.

    So far, I have one plate with two colliders for the left and right.

    upload_2023-12-7_11-50-8.png

    Then when the left plate touches the collider it will parent it and set it's transforms to align itself, but this relies on an offset value which could become very tedious when I introduce new shapes. Plus it makes the potential for object creation very limited, since it will only work for a few angles. Then for more complex shapes I'd need loads more colliders and so on.

    upload_2023-12-7_11-50-47.png

    What I was hoping to do was make it so that if the other plate touches the other, it will keep its rotation, but connect the nearest edge to the closest part of the face like this quick sketch below, but I'm not too sure how I could do that.

    upload_2023-12-7_11-54-24.png

    With the rigidbody system, is it possible to kind of retrieve the place that two colliders intersected? And if you can get that information, how could you connect one edge to another?

    This is the code I have so far.
    Code (CSharp):
    1. public class MultiPartColliderDetector : MonoBehaviour
    2. {
    3.     public UnityEvent<Collider> OnCollisionEnter;
    4.     public UnityEvent<Collider> OnCollisionExit;
    5.     private void OnTriggerEnter(Collider other)
    6.     {
    7.         if (other.CompareTag("Snappable"))
    8.         {
    9.             OnCollisionEnter?.Invoke(other);
    10.             Debug.Log(other.name + " entered");
    11.         }
    12.     }
    13.  
    14.  
    15. }
    Code (CSharp):
    1. public class SnappablePlane : MonoBehaviour
    2. {
    3.     public MultiPartColliderDetector leftTrigger;
    4.     public MultiPartColliderDetector rightTrigger;
    5.     public GameObject otherObject;
    6.     public Vector3 snapOffset = new Vector3 (0, 0, 1);
    7.     private Rigidbody otherRb;
    8.     // Start is called before the first frame update
    9.     void Start()
    10.     {
    11.        
    12.     }
    13.  
    14.     // Update is called once per frame
    15.     void Update()
    16.     {
    17.        
    18.     }
    19.  
    20.     private void Awake()
    21.     {
    22.         leftTrigger.OnCollisionEnter.AddListener(OnLeftTriggerEntered);
    23.         rightTrigger.OnCollisionEnter.AddListener (OnRightTriggerEntered);
    24.     }
    25.  
    26.     public void OnLeftTriggerEntered(Collider collider)
    27.     {
    28.         otherObject = collider.gameObject;
    29.         otherRb = otherObject.GetComponent<Rigidbody>();
    30.         otherRb.isKinematic = true;
    31.         otherRb.detectCollisions = false;
    32.         transform.GetChild(0).gameObject.SetActive(false);
    33.         transform.GetChild(1).gameObject.SetActive(false);
    34.         otherObject.transform.position = transform.position + snapOffset;
    35.         otherObject.transform.rotation = transform.rotation;
    36.         Destroy(otherRb);
    37.         otherObject.transform.parent = transform;
    38.         Debug.Log(gameObject.name + " has entered the left trigger");
    39.        
    40.  
    41.  
    42.     }
    43.  
    44.     public void OnRightTriggerEntered(Collider collider)
    45.     {
    46.         otherObject = collider.gameObject;
    47.         otherRb = otherObject.GetComponent<Rigidbody>();
    48.         otherRb.isKinematic = true;
    49.         otherRb.detectCollisions = false;
    50.         transform.GetChild(0).gameObject.SetActive(false);
    51.         transform.GetChild(1).gameObject.SetActive(false);
    52.         otherObject.transform.position = transform.position + snapOffset;
    53.         otherObject.transform.rotation = transform.rotation;
    54.         Destroy(otherRb);
    55.         otherObject.transform.parent = transform;
    56.         Debug.Log(gameObject.name + " has entered the right trigger");
    57.     }
    58. }