private void Start()
    {
        // Create magic beam point array for curve.
        m_MagicBeamPoints = new Vector3[3];

        // Make sure there's a place available for this to go if controllers aren't found. This is typically a child of the HMD/Camera.
        // If not, log an error.
        if (!m_ControllerPreferences[m_ControllerPreferences.Length - 1].siblingGO.activeSelf)
        {
            Debug.LogError("Telekinesis: Last Controller Preference GameObject must always be enabled, as a viable fallback.");
        }

        // Set a default controller.
        m_CurrentController = m_ControllerPreferences[0];

        // Assign the line renderer if we have one.
        if (GetComponent <LineRenderer>())
        {
            m_Line = GetComponent <LineRenderer>();
        }
    }
    void Update()
    {
        // Keep this raycaster positionally mapped to the active controller transfrom
        transform.position = m_CurrentController.siblingGO.transform.position;
        transform.rotation = m_CurrentController.siblingGO.transform.rotation;

        // If we have a line, set it's positions
        if (m_Line != null)
        {
            m_Line.positionCount = 2;
            m_Line.SetPosition(0, transform.position);
            m_Line.SetPosition(1, transform.position + transform.forward * 1f);
        }

        // If we have a reticle, position it forward from the controller.
        if (m_Reticle != null)
        {
            m_Reticle.position = transform.position + transform.forward * 5f;
            m_Reticle.rotation = Quaternion.FromToRotation(Vector3.forward, transform.position - (transform.position + transform.forward * 1f));
        }

        // See if we can get a preferred controller, or fall back if our current controller is disconnected.
        for (int i = 0; i < m_ControllerPreferences.Length; i++)
        {
            if (m_ControllerPreferences[i].siblingGO.activeSelf)
            {
                if (m_ControllerPreferences[i] != m_CurrentController)
                {
                    // Drop object if controller is lost.
                    Detach();
                    // Set new current controller
                    m_CurrentController = m_ControllerPreferences[i];
                }
                break;
            }
        }

        // If we're "telekinesising" do this stuff to move the object.
        if (m_IsTelekinesising)
        {
            // Check touchpad Y value to see if we should push or pull the object.
            if (m_CurrentController.GetY() > .5f)
            {
                m_fDistance += m_DepthSpeed;
            }
            else if (m_CurrentController.GetY() < -.5f)
            {
                m_fDistance -= m_DepthSpeed;
            }

            // Move in relation to the controller.
            // Get the rigid body.
            Rigidbody rigidBody = m_ActiveObject.gameObject.GetComponent <Rigidbody>();
            // Get the point directly in front of the controller, at the distance of the object.
            Vector3 targetPos = (transform.position + (transform.forward * m_fDistance));
            // Find out how far the object is from the target pos. This will contribute to how much force is applied.
            float travelDistance = Vector3.Distance(targetPos, m_ActiveObject.transform.position);

            // Adjust drag to aid in natural stopping/recoil, based on distance to travel.
            rigidBody.drag = Remap(Mathf.Min(travelDistance, .1f), m_InitialDrag, 5, 5, m_InitialDrag);
            // Add force in the direction we need to travel.
            rigidBody.AddForce((targetPos - m_ActiveObject.transform.position) * (travelDistance * m_FollowSpeed));

            // If we want to allow rotating the object...
            if (m_AllowRotate)
            {
                // Get the controller Z angle
                float RotateZAmount = Mathf.DeltaAngle(m_LastControllerAngle, transform.eulerAngles.z);
                // Rotate the object by the same amount
                m_ActiveObject.transform.Rotate(transform.forward, RotateZAmount, Space.World);
                // Record last applied controller angle
                m_LastControllerAngle = transform.eulerAngles.z;

                // If the user is touching the far left/right of the touchpad, rotate on the up axis in the appropriate direction
                if (m_CurrentController.GetX() > .5f || m_CurrentController.GetX() < -.5f)
                {
                    float RotateXAmount = m_CurrentController.GetX() * 90f;
                    m_ActiveObject.transform.Rotate(-transform.up, RotateXAmount * Time.deltaTime, Space.World);
                }
            }

            // Set up the origin, influence and destination for the Magic Beam curve.
            m_MagicBeamPoints[0] = transform.position;
            m_MagicBeamPoints[1] = transform.position + (transform.forward * Vector3.Distance(m_ActiveObject.transform.position, transform.position) / 2);
            m_MagicBeamPoints[2] = m_ActiveObject.transform.position;

            // Get the curve
            Vector3[] Curve = QuadraticBezierCurve(m_MagicBeamPoints[0], m_MagicBeamPoints[1], m_MagicBeamPoints[2], m_PathParticleCount);

            // Place a the magic beam particle on each point of the curve.
            int i = 0;
            foreach (Vector3 point in Curve)
            {
                Transform part = m_ParticleHolder.transform.GetChild(i);
                part.position = point;
                float scaleFactor = Remap(Mathf.Min(Vector3.Distance(m_ActiveObject.transform.position, transform.position), 10), 0, 10, .3f, .6f);
                part.localScale = ((Vector3.one / m_PathParticleCount) * i) * scaleFactor;
                part.LookAt(transform.transform);
                i++;
            }
            // If we detect that the button is up while we're telekinesising, drop the object.
            if (!m_CurrentController.GetButton() && !Input.GetMouseButton(0))
            {
                Detach();
            }
        }
        // If we're not "Telekinesising"...
        else
        {
            // Cast a ray forward to see what we hit.
            Ray        ray = new Ray(transform.position, transform.forward);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, m_MaxDistance, ~m_ExclusionLayers))
            {
                // If we have a reticle, Position/Angle it just above the surface it hit.
                if (m_Reticle != null)
                {
                    m_Reticle.position = hit.point;
                    m_Reticle.rotation = Quaternion.FromToRotation(Vector3.forward, hit.normal);
                }
                // If the object we're pointing at is a TelekinesisObject and we've detected a button down (while not already telekinesising), pick it up.
                if ((m_CurrentController.GetButton() || Input.GetMouseButton(0)) && hit.collider.gameObject.GetComponent <VRTelekinesisObject>())
                {
                    Attach(hit.collider.gameObject.GetComponent <VRTelekinesisObject>());
                }
            }
        }

        // Record what direction to throw the object when we detach.
        m_DropVel = (transform.position - GetMeanVector(lastPositionQueue)) / Time.deltaTime;

        // Update a queue of positions to average to get average velocity
        if (lastPositionQueue.Count >= maxQueueSize)
        {
            lastPositionQueue.Dequeue();
        }
        lastPositionQueue.Enqueue(transform.position);
    }