Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Make two objects in 3D space snap to each others boundaries

Discussion in 'Scripting' started by toreau, Apr 4, 2014.

  1. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    Hi!

    I'm playing around with a first-person "construction" game where I can carry objects in front of me (ie. in front of the camera), place them on the ground and that way build bigger things. Assume we are talking about cubes (ie. for a floor) in this case.

    Both the carrying things around and placing them on the ground is not a problem. The problem is that I want to snap the object I'm currently holding to another object whenever it gets close enough. And it have to snap to the closest side of the other object.

    So far I've got this:

    Code (csharp):
    1. // Update is called once per frame
    2. void Update () {
    3.  
    4.     if ( itemObject != null ) {
    5.  
    6.         // Are we holding an object?
    7.         if ( isHoldingObject ) {
    8.  
    9.             // Let the itemObject follow the camera
    10.             itemObject.transform.rotation = new Quaternion( 0.0f, playerCamera.transform.rotation.y, 0.0f, playerCamera.transform.rotation.w );
    11.             itemObject.transform.position = playerCamera.transform.position + playerCamera.transform.forward * distance;
    12.        
    13.             // Are there any other objects close to this itemObject that it can connect to?
    14.             GameObject nearestObject = FindNearestConstructableObject( itemObject );
    15.  
    16.             // Do we have a constructable object close enough?
    17.             if ( nearestObject != null ) {
    18.  
    19.                 // Make itemObject the child of nearestObject
    20.                 itemObject.transform.parent = nearestObject.transform;
    21.  
    22.                 // Make sure they have the same rotation (because the objects' texture adds up and it looks good)
    23.                 itemObject.transform.rotation = nearestObject.transform.rotation;
    24.  
    25.                 // Snap itemObject to nearestObject
    26.                 itemObject.transform.localPosition = WHAT?!
    27.  
    28.             }
    29.             else {
    30.                 itemObject.transform.parent = null;
    31.             }
    32.  
    33.             // "Let go" of the object
    34.             if ( Input.GetButtonDown("Fire1") ) {
    35.                 if ( nearestObject != null ) {
    36.                     // Maybe nothing has to be done here?
    37.             }
    38.  
    39.                 isHoldingObject = false;
    40.             }
    41.  
    42.         }
    43.  
    44.     }
    45.  
    46. }
    47.  
    48. // Returns the nearest constructable object relative to "anObject"
    49. private GameObject FindNearestConstructableObject ( GameObject anObject, float maxDistance = 1.5f ) {
    50.     Collider[] colliders = Physics.OverlapSphere( anObject.transform.position, maxDistance );
    51.     Collider closestCollider = null;
    52.  
    53.     foreach ( Collider hit in colliders ) {
    54.  
    55.         if ( hit.collider == anObject.collider ) {
    56.             continue;
    57.         }
    58.  
    59.         if ( hit.collider.gameObject.tag != "Constructable" ) {
    60.             continue;
    61.         }
    62.  
    63.         if ( !closestCollider ) {
    64.             closestCollider = hit;
    65.         }
    66.  
    67.         if ( Vector3.Distance(anObject.transform.position, hit.transform.position) <= Vector3.Distance(anObject.transform.position, closestCollider.transform.position) ) {
    68.             closestCollider = hit;
    69.         }
    70.  
    71.     }
    72.    
    73.     return ( closestCollider ) ? closestCollider.gameObject : null;
    74. }
    Any suggestions to what to put on line #26 in the code above? Any other suggestions which can improve this is also welcome, of course. :)

    Thanks in advance!
     
  2. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    I came up with something super-simple myself:

    Code (csharp):
    1. itemObject.transform.localPosition = new Vector3(
    2.     Mathf.RoundToInt( itemObject.transform.localPosition.x ),
    3.     0,
    4.     Mathf.RoundToInt( itemObject.transform.localPosition.z )
    5. );
    (The reason why the "y" value is 0, is that all these objects will always be aligned vertically to each other...)

    It works, kind of, but it also snaps the two cubes to each other on the corners. Not sure if this is a feature or not, but it's anyway a step forward. :)