Search code examples
c#unity-game-enginegameobject

Snapping game object to another game object in Unity 3D during runtime


At this moment, I drag my game-object across the screen; however, I'm having a hard time figuring out how to have my game-object snap to pre-existing game-object in my scene. How do I have my game-object snapped to another object during run time once it is instantiated?

public class DragObject : MonoBehaviour

{ 
    private Vector3 mOffset;
    private float mZCoord;

    void OnMouseDown()

    {
        mZCoord = Camera.main.WorldToScreenPoint(
        gameObject.transform.position).z;
        mOffset = gameObject.transform.position - GetMouseAsWorldPoint();
    }

    private Vector3 GetMouseAsWorldPoint()

    {
        Vector3 mousePoint = Input.mousePosition;
        mousePoint.z = mZCoord;
        return Camera.main.ScreenToWorldPoint(mousePoint);
    }

    void OnMouseDrag()

    {
        transform.position = GetMouseAsWorldPoint() + mOffset;
    }

}

LoadAssets class:

public class LoadAssets : MonoBehaviour
{

    bool isCreated = false;
    bool isCreatedDrillbit = false;

    public void LoadBOP()

    {
        if (!isCreated)

        {
            GameObject instance = Instantiate(Resources.Load("BOP", typeof(GameObject))) as GameObject;
            isCreated = true;
        }

    }

    public void LoadDrillBit()

    {
        if (!isCreatedDrillbit)

        {
            GameObject instance = Instantiate(Resources.Load("Drillbit", typeof(GameObject))) as GameObject;
            isCreatedDrillbit = true;
        }

    }

}

Solution

  • Write a script that checks the position of some other object, and if it's close enough, make it a child of itself and set its local position and rotation to be the default. Also, disable the dragging script:

    public class SnapToMe : MonoBehaviour
    {
    
        public GameObject target = null;
        public float snapDistance = 1f; 
    
        void FixedUpdate() 
        {
            if (target==null) return;
    
            if ( Vector3.Distance(transform.position, target.transform.position) <= snapDistance) )  
            {
                target.transform.parent = transform;
                target.transform.localRotation = Quaternion.identity;
                target.transform.localPosition = Vector3.zero;
    
                target.GetComponent<DragObject>().enabled = false;
            }
        }
    }
    

    On the object you'd like to do the snapping, add a child object where the snapping should occur, and attach the snapping script to it:

    Bottle
    └── Bottle snap point
        └── SnapToMe
    

    Then when you create the cap, tell the snap point about it:

    Gameobject newCap = Instantiate(...);
    Gameobject bottleSnapPoint = GameObject.Find(
            "Bottle snap point"); // or some other way to get a reference to the snap point
    
    SnapToMe snapper = bottleSnapPoint.GetComponent<SnapToMe>();
    snapper.target = newCap;
    snapper.snapDistance = 2f; //whatever is appropriate