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); }