// Grab the object
    void Attach(VRTelekinesisObject obj)
    {
        if (!m_IsTelekinesising)
        {
            // Kill the line/reticle while telekinesising
            if (m_Line != null)
            {
                m_Line.enabled = false;
            }
            m_Reticle.GetComponentInChildren <MeshRenderer>().enabled = false;

            // Record that we're actively controlling the object.
            m_IsTelekinesising = true;

            // Update the active object to the one we clicked on.
            m_ActiveObject = obj;

            // Create a game object to hold all of the Magic Beam particles
            m_ParticleHolder = new GameObject();
            m_ParticleHolder.transform.parent = transform;
            for (int i = 0; i < m_PathParticleCount; i++)
            {
                GameObject go = Instantiate(m_PathParticle);
                go.transform.parent = m_ParticleHolder.transform;
            }
            // Enable each particle
            ParticleSetEnabled(true);

            // Get the object's rigid body
            Rigidbody rigidBody = m_ActiveObject.gameObject.GetComponent <Rigidbody>();
            // Remember it's drag/gravity values for restoration later.
            m_InitialDrag        = rigidBody.drag;
            m_InitialAngularDrag = rigidBody.angularDrag;
            m_OriginalGravity    = rigidBody.useGravity;
            // Set Angular Drag to huge amount, making the object initially stationary.
            rigidBody.angularDrag = float.MaxValue;
            // Disable gravity so we don't have to fight it while moving the object through the air.
            rigidBody.useGravity = false;
            // Set collision detection to continuous to avoid going through other objects.
            rigidBody.collisionDetectionMode = CollisionDetectionMode.Continuous;
            // Record the initial distance between the user and the object grabbed.
            m_fDistance = Vector3.Distance(m_ActiveObject.transform.position, transform.position);

            // Notify subscribers of the new object.
            if (OnAttach != null)
            {
                OnAttach(m_ActiveObject);
            }
        }
    }
    // Drop the object.
    void Detach()
    {
        if (m_IsTelekinesising)
        {
            // Enable the line while not telekinesising
            if (m_Line != null)
            {
                m_Line.enabled = true;
            }
            m_Reticle.GetComponentInChildren <MeshRenderer>().enabled = true;

            // Record that we're done.
            m_IsTelekinesising = false;

            // Restore all of the rigidbody values (as recorded in Attach())
            Rigidbody rigidBody = m_ActiveObject.gameObject.GetComponent <Rigidbody>();
            rigidBody.drag                   = m_InitialDrag;
            rigidBody.angularDrag            = m_InitialAngularDrag;
            rigidBody.useGravity             = m_OriginalGravity;
            rigidBody.collisionDetectionMode = CollisionDetectionMode.Discrete;
            m_fDistance = 0f;

            // Add force to allow enhanced "throw" feel.
            rigidBody.AddForce(m_DropVel.x * m_ThrowForce, m_DropVel.y * m_ThrowForce, m_DropVel.z * m_ThrowForce, ForceMode.Impulse);

            // Disable all of the particles and destroy their parent.
            ParticleSetEnabled(false);
            Destroy(m_ParticleHolder);

            // Notify subscribers of the drop
            if (OnDetach != null)
            {
                OnDetach(m_ActiveObject);
            }

            // Clear Active Telekinesis Object reference
            m_ActiveObject = null;
        }
    }