Search Unity

Align an object to a surface

Discussion in 'Scripting' started by kityanlam3, Jun 16, 2016.

  1. kityanlam3

    kityanlam3

    Joined:
    Feb 2, 2016
    Posts:
    41
    upload_2016-6-16_13-55-10.png
    I have a script that lets player move objects around with the mouse and when player clicks it will attach itself to the wall. In the above picture I have a cube that the player has attached to a wall, however half of the cube goes inside the wall. I don't want that, the cube should be fully visible and attached to the wall.

    Here's the code that I currently use, any help is appreciated.

    Code (CSharp):
    1.  //If the object is wall furniture run code.
    2.             else if (currentfurniture.gameObject.tag == "WallFurniture")
    3.             {
    4.                 //If not already holding an object run this code.
    5.                 if (!HoldingObject)
    6.                 {
    7.                     nowyoucanrun = false;
    8.                     Vector3 m = Input.mousePosition;
    9.                     m = new Vector3(m.x, m.y, transform.position.y);
    10.                     Vector3 p = Camera.main.ScreenToWorldPoint(m);
    11.                     //Object follows cursor
    12.                     currentfurniture.position = new Vector3(p.x, 5, p.z);
    13.                     if (Input.GetMouseButtonDown(0) && nowyoucanrun == false)
    14.                     {
    15.  
    16.                         //fm._canvas1.SetActive(true);
    17.  
    18.                         RaycastHit[] hits = new RaycastHit[4];
    19.  
    20.                         //Fire multiple rays to find shortest distance
    21.                         Physics.Raycast(currentfurniture.position, Vector3.forward, out hits[0]);
    22.                         Physics.Raycast(currentfurniture.position, Vector3.back, out hits[1]);
    23.                         Physics.Raycast(currentfurniture.position, Vector3.left, out hits[2]);
    24.                         Physics.Raycast(currentfurniture.position, Vector3.right, out hits[3]);
    25.  
    26.                         //Check array to find shortest distance and hit.
    27.                         float smallestdist = hits[0].distance;
    28.                         RaycastHit target = hits[0];
    29.                      
    30.                         foreach (RaycastHit t in hits)
    31.                         {
    32.                             if (t.distance < smallestdist)
    33.                             {
    34.                                 smallestdist = t.distance;
    35.                                 target = t;
    36.                             }
    37.                          
    38.                         }
    39.                         Debug.Log(smallestdist);
    40.                         Debug.Log(target.transform.name);
    41.                         //Set position of cube
    42.                         currentfurniture.position = new Vector3(target.point.x, 5, target.point.z);
    43.                      
    44.                         camera.cameraFreezerot = false;
    45.                         HoldingObject = false;
    46.                         nowyoucanrun = true;
    47.                      
    48.                         currentfurniture = null;
    49.  
    50.  
    51.                     }
    52.                 }
     
  2. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    You need to offset your position vector by half the width of the cube. Use the RaycastHit normal to determine the direction of offset.
     
    Last edited: Jun 16, 2016
  3. kityanlam3

    kityanlam3

    Joined:
    Feb 2, 2016
    Posts:
    41
    Sorry, but how will I get half the width of the cube and even though I looked at the docs I still don't understand how RaycastHit.normal works also for additional info, I plan to have other objects besides cubes like chairs and beds.
     
    Last edited: Jun 16, 2016
  4. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    I think the easiest way would be to use Mesh.bounds(https://docs.unity3d.com/ScriptReference/Mesh-bounds.html). You could then use the extents of the bounds for your offset as they would be half the width of the mesh for each axis. RaycastHit.normal is the facing direction of the surface your ray hit.

    The normals are the pink arrows:
     
    Last edited: Jun 16, 2016
  5. kityanlam3

    kityanlam3

    Joined:
    Feb 2, 2016
    Posts:
    41
    Thanks for the visual image, much clearer. I'll try the bounds method.