private void Awake() { cachedTrans = transform; cachedCam = GetComponent <Camera>(); currentlyHolding = null; prevHeldVelocity = 0f; curDragDistance = defaultDragDistance; }
private void Update() { // Control the hand rig positioning and try to avoid clipping using the raycast. UpdateHandVisual(); // Controlling hand distance by scrolling. float scrollWheel = Input.GetAxis("Mouse ScrollWheel"); if (scrollWheel < -Mathf.Epsilon) { curDragDistance -= dragDistanceStep; curDragDistance = Mathf.Max(minDragDistance, curDragDistance); } else if (scrollWheel > Mathf.Epsilon) { curDragDistance += dragDistanceStep; curDragDistance = Mathf.Min(curDragDistance, maxDragDistance); } // Handle dragging and releasing/tossing an object. if (Input.GetMouseButtonDown(0)) { Ray rayToCursor = cachedCam.ScreenPointToRay(Input.mousePosition); RaycastHit hit; // Buffer distance to allow grabbing objects further from hand. float rayDistance = curDragDistance * 2f; if (Physics.Raycast(rayToCursor, out hit, rayDistance)) { if (currentlyHolding != null) { // Ensure previously held object is released before holding new object. ReleaseHeldObject(); } TossableObject tossable = hit.collider.GetComponent <TossableObject>(); if (tossable != null) { // Grab the object so that it's centered around where the cursor was on the object. grabObjOffset = hit.collider.bounds.center - hit.point; HoldObject(tossable); } } } else { if (Input.GetMouseButtonUp(0) && currentlyHolding != null) { ReleaseHeldObject(); } } }
private void HoldObject(TossableObject obj) { if (obj == null) { ReleaseHeldObject(); return; } currentlyHolding = obj; prevHeldVelocity = obj.cachedRigid.velocity.magnitude; // Updating hand distance to where the visual hand is. curDragDistance = visualHandDist; curDragDistance = Mathf.Clamp(curDragDistance, minDragDistance, maxDragDistance); // Send grab event. currentlyHolding.OnGrabbed(); // "Freeze" rotation while held. Restore angular drag upon releasing. rigidOrigAngDrag = obj.cachedRigid.angularDrag; obj.cachedRigid.angularDrag = 10f; }
private void ReleaseHeldObject() { if (currentlyHolding == null) { return; } // No need to add force since the velocity is already set during drag in FixedUpdate. // Restore original angular drag prior to grabbing. currentlyHolding.cachedRigid.angularDrag = rigidOrigAngDrag; // Add torque based on multiple factors. // Faster objects have more torque. float velocityTorqueFactor = currentlyHolding.cachedRigid.velocity.magnitude * 0.0005f; // Grabbing object near the edge will add more torque as opposed to grabbing near middle. float grabOffCenterTorqueFactor = grabObjOffset.magnitude * 0.002f; float torqueAmount = 0.0005f + velocityTorqueFactor + grabOffCenterTorqueFactor; currentlyHolding.cachedRigid.AddTorque(Random.onUnitSphere * torqueAmount, ForceMode.Impulse); // Send toss event for boomerang and other behaviors. currentlyHolding.OnTossed(); currentlyHolding = null; }